我想要做的是在緩衝區上繪製圖形,然後將其原樣複製到畫布上,這樣我就可以進行動畫並避免閃爍。但我找不到這個選項。任何人都知道我可以如何去做這件事?HTML5/Canvas支持雙緩衝嗎?
回答
下有用的鏈接,除了展示的例子,並使用雙緩衝的優勢,展示了使用HTML5的Canvas元素其他一些性能提示。它包含jsPerf測試的鏈接,它將瀏覽器的測試結果彙總到一個Browserscope數據庫中。這可確保性能提示得到驗證。
http://www.html5rocks.com/en/tutorials/canvas/performance/
爲方便起見,我已包括在文章中描述的有效的雙緩衝的最小例子。
// canvas element in DOM
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');
// buffer canvas
var canvas2 = document.createElement('canvas');
canvas2.width = 150;
canvas2.height = 150;
var context2 = canvas2.getContext('2d');
// create something on the canvas
context2.beginPath();
context2.moveTo(10,10);
context2.lineTo(10,30);
context2.stroke();
//render the buffered canvas onto the original canvas element
context1.drawImage(canvas2, 0, 0);
而不是滾動您自己,你可能會使用現有的庫,以獲得最佳里程爲創造清潔,無閃爍的JavaScript動畫:
這裏有一個流行的一種:http://processingjs.org
一非常簡單的方法是在同一屏幕位置放置兩個畫布元素,併爲您需要顯示的緩衝區設置可見性。當你完成後,在隱藏處畫畫並翻轉。
某些代碼:
CSS:
canvas { border: 2px solid #000; position:absolute; top:0;left:0;
visibility: hidden; }
翻轉在JS:
Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';
DrawingBuffer=1-DrawingBuffer;
在此代碼陣列 '緩衝器[]' 同時擁有畫布對象。所以,當你要開始繪製你仍然需要獲得上下文:
var context = Buffers[DrawingBuffer].getContext('2d');
不錯的解決方案:D – 2011-07-05 13:36:21
偏題:我個人喜歡用'
瀏覽器我測試過的所有,直到吸引你的框架代碼完成時不重畫在畫布上處理這個緩衝你。請參閱WHATWG郵件列表:http://www.mail-archive.com/[email protected]/msg19969.html
好吧,我注意到閃爍或屏幕撕裂。不知道如何描述它。在Linux上使用最新的Chrome。 – grom 2012-07-27 04:45:17
Opera 9.10非常慢並顯示繪圖過程。如果你想看到瀏覽器不使用雙緩衝,請嘗試Opera 9.10。
有些人建議瀏覽器以某種方式確定繪圖過程何時結束,但您能否解釋這可以如何工作?即使畫圖很慢,我也沒有注意到Firefox,Chrome或IE9中有任何明顯的閃爍,所以看起來這就是他們正在做的事情,但是如何實現這一點對我來說是個謎。在更多的繪圖指令被執行之前,瀏覽器如何知道它正在刷新顯示?你認爲他們只是計時嗎?如果超過5毫秒的時間間隔沒有執行畫布繪圖指令,它會認爲它可以安全地交換緩衝區?
需要2個帆布:(注意CSS的z-index和位置:絕對)
<canvas id="layer1" width="760" height="600" style=" position:absolute; top:0;left:0;
visibility: visible; z-index: 0; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="layer2" width="760" height="600" style="position:absolute; top:0;left:0;
visibility: visible; z-index: 1; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
,你可以看到,第一畫布上是可見的,它是隱藏它借鑑隱藏的想法第二之後,我們將隱藏可見並使隱藏的畫布可見。當它是隱藏的「清除隱藏的帆布
<script type="text/javascript">
var buff=new Array(2);
buff[0]=document.getElementById("layer1");
buff[1]=document.getElementById("layer2");
ctx[0]=buff[0].getContext("2d");
ctx[1]=buff[1].getContext("2d");
var current=0;
// draw the canvas (ctx[ current ]);
buff[1- current ].style.visibility='hidden';
buff[ current ].style.visibility='visible';
ctx[1-current].clearRect(0,0,760,600);
current =1-current;
對於不信的人,這裏有一些閃爍的代碼。請注意,我明確地清除了以前的圈子。
http://coderextreme.net/basketball2.html(http://jsfiddle.net/GzSWJ/)
<!DOCTYPE html>
<html>
<head><title>Basketball</title></head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw_ball(ball) {
ctx.clearRect(0, 0, 400, 400);
ctx.fillStyle = "#FF0000";
ctx.beginPath();
ctx.arc(ball.x, ball.y, 30, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
var deltat = 1;
var ball = {};
ball.y = 0;
ball.x = 200;
ball.vy = 0;
ball.vx = 10;
ball.ay = 9.8;
ball.ax = 0.1;
function compute_position() {
if (ball.y > 370 && ball.vy > 0) {
ball.vy = -ball.vy * 84/86;
}
if (ball.x < 30) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
} else if (ball.x > 370) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
}
ball.ax = ball.ax/2;
ball.vx = ball.vx * 185/186;
ball.y = ball.y + ball.vy * deltat + ball.ay * deltat * deltat/2
ball.x = ball.x + ball.vx * deltat + ball.ax * deltat * deltat/2
ball.vy = ball.vy + ball.ay * deltat
ball.vx = ball.vx + ball.ax * deltat
draw_ball(ball);
}
setInterval(compute_position, 40);
</script></body></html>
喬什問(而回)關於瀏覽器如何知道「什麼時候繪製過程結束」,以避免閃爍。我會直接評論他的帖子,但我的代表不夠高。這也只是我的看法。我沒有支持它的事實,但我對此相當有信心,未來讀者可能會對此有所幫助。
我猜測你完成繪圖時瀏覽器並不知道。但是就像大多數JavaScript一樣,只要代碼在不放棄對瀏覽器的控制權的情況下運行,瀏覽器就會被鎖定,並且不會更新/響應其UI。我在猜測,如果你清除畫布並畫出整個畫面而不放棄對瀏覽器的控制,那麼在完成之前它不會實際繪製畫布。
如果您設置了一種情況,即您的渲染跨越多個setTimeout/setInterval/requestAnimationFrame調用,您可以在一次調用中清除畫布,並在接下來的幾次調用中在畫布上繪製元素,每次重複循環5次電話,我願意打賭你會看到閃爍,因爲每次通話後畫布都會更新。
這就是說,我不確定我會相信這一點。我們已經認識到,JavaScript在執行之前會被編譯爲本地機器代碼(至少這是Chrome的V8引擎根據我的理解所做的)。如果瀏覽器在與用戶界面不同的線程中開始運行它們的javascript並同步對UI元素的任何訪問,以允許UI在不訪問UI的JavaScript執行期間更新/響應,我不會感到驚訝。當/如果發生這種情況(並且我知道有許多障礙需要克服,例如事件處理程序在您仍在運行其他代碼時開始運行),我們可能會看到未使用的畫布動畫閃爍某種雙緩衝。
就我個人而言,我喜歡將兩個畫布元素放置在彼此頂部並交替顯示/在每個畫面上繪製的想法。相當不引人注意,可能很容易通過幾行代碼添加到現有應用程序中。
正確。例如,查看JSFiddle http://stackoverflow.com/questions/11777483/do-we-need-to-implement-double-buffering-ourselves-with-canvas。 – Eric 2013-08-01 03:51:27
在大多數情況下,您不需要執行此操作,瀏覽器會爲您執行此操作。 但並不總是有用!
當你的繪圖非常複雜時,你仍然需要實現這一點。 大部分的屏幕更新率大約是60Hz,這意味着屏幕每16ms更新一次。瀏覽器的更新率可能接近這個數字。如果你的形狀需要100ms完成,你會看到一個未完成的形狀。所以你可以在這種情況下實現雙緩衝。
我做了一個測試:Clear a rect, wait for some time, then fill with some color.
如果我把時間設置爲10ms,我就不會看到閃爍。但是如果我將其設置爲20ms,閃爍就會發生。
您如何解釋使用雙緩衝技術所見證的性能改進? http://www.html5rocks.com/en/tutorials/canvas/performance/ – ricksuggs 2013-10-11 13:58:52
@ricksuggs那麼,html5rocks上提到的「雙緩衝」或「離屏渲染」與我想的有點不同。我認爲DB是交換屏幕頁面(在vram中),這實際上只是一個指針操作,而不是複製內存塊。 OP要求使用DB來避免閃爍,這是通過requestAnimationFrame()真正解決的。也許這個[文章](http://tinyurl.com/lpnkfnj)關於屏外渲染可能很有趣。在那裏,我回答了關於使用Sprite Buffer – ohager 2014-06-04 17:21:55
你總是可以做 var canvas2 = document.createElement("canvas");
而不是將它追加到DOM。
只是說,因爲你們似乎很迷戀display:none;
它只是看起來更清潔,模仿雙緩衝方式的想法比只是一個笨拙的無形畫布更準確。
le在4歲麪包上烤麪包的方法將緩衝圖像數據複製並粘貼到屏幕上的問題:-DD – DeadlyBacon 2016-01-16 12:23:46
答案仍然幫助我:D – AME 2017-06-09 07:59:44
- 1. GDI +雙緩衝
- 2. Jython雙緩衝
- 3. VB.NET雙緩衝
- 4. Java雙緩衝
- 5. 雙緩衝swt
- 6. WinAPI雙緩衝
- 7. Android雙緩衝
- 8. TypeError:'str'不支持緩衝接口
- 9. Python3.4'str'dons不支持緩衝區接口
- 10. TypeError:str不支持緩衝區接口
- 11. 雙緩衝幫助
- 12. Silverlight MediaElement雙緩衝
- 13. 啓用雙緩衝
- 14. 的WinForms雙緩衝
- 15. Java - 雙緩衝NullPointerException
- 16. DrawReversibleLine()和雙緩衝
- 17. 在c#雙緩衝
- 18. Android上支持雙向SSL握手嗎?
- 19. C++ win32項目雙緩衝
- 20. 雙緩衝VB6 BitBlt幫助
- 21. C++的Win32 GDI雙緩衝
- 22. Direct2D中的雙緩衝?
- 23. 瞭解雙緩衝區
- 24. Qt的雙緩衝行爲
- 25. GDI + C++中的雙緩衝
- 26. 黑莓雙緩衝區?
- 27. 的Java Swing的雙緩衝
- 28. 的java雙緩衝問題
- 29. WPF中的雙緩衝?
- 30. Android雙卡API支持
我的經驗是,帆布畫是由瀏覽器合併,使動畫順利。你能分享一些閃爍的代碼嗎? – eyelidlessness 2010-05-08 19:10:42
我注意到IE在使用'explorercanvas'時可能會閃爍,但這當然不是HTML5,並且是僅由VML模擬的'canvas'元素。我從來沒有見過其他瀏覽器這樣做。 – cryo 2010-05-19 10:16:54
相關http://stackoverflow.com/questions/11777483/ – julien 2012-11-29 14:48:12