HTML5/Canvas 是否支持双缓冲?

IT技术 javascript html canvas double-buffering
2021-01-14 19:33:17

我想要做的是在缓冲区上绘制我的图形,然后能够将其按原样复制到画布上,这样我就可以制作动画并避免闪烁。但是我找不到这个选项。有谁知道我该怎么做?

6个回答

一个非常简单的方法是在同一屏幕位置放置两个画布元素,并为需要显示的缓冲区设置可见性。完成后在隐藏处绘制并翻转。

一些代码:

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;

在此代码中,数组 'Buffers[]' 包含两个画布对象。所以当你想开始绘图时,你仍然需要获取上下文:

var context = Buffers[DrawingBuffer].getContext('2d');
题外话:我个人喜欢使用<noscript>, 并在 Javascript 中创建我的画布元素。无论如何,您通常都希望在 Javascript 中检查画布支持,那么为什么要在 HTML 中放置画布回退消息呢?
2021-03-24 19:33:17

以下有用的链接除了显示使用双缓冲的示例和优势之外,还显示了使用 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);

我测试过的所有浏览器都通过在绘制框架的代码完成之前不重新绘制画布来为您处理这种缓冲。另请参阅 WHATWG 邮件列表:http : //www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html

好吧,我注意到闪烁或屏幕撕裂。不知道怎么形容。在 Linux 上使用最新的 Chrome。
2021-04-02 19:33:17

你总是可以这样做 var canvas2 = document.createElement("canvas"); 而不是将它附加到 DOM 中。

只是说,因为你们似乎display:none; 对它如此着迷,对我来说似乎更干净,并且比仅仅拥有一个笨拙的隐形画布更准确地模仿双缓冲方式的想法。

两年多后:

不需要“手动”实现双缓冲。Geary 先生在他的书“HTML5 Canvas”中写到了这一点

有效减少闪烁使用requestAnimationFrame()

您如何解释使用双缓冲所见证的性能改进?html5rocks.com/en/tutorials/canvas/performance
2021-03-26 19:33:17
@ricksuggs 嗯,html5rocks 上提到的“双缓冲”或“屏幕外渲染”与我想象的有点不同。我认为 DB 是交换屏幕页面(在 vram 中),这实际上只是一个指针操作,而不是复制内存块。OP 要求使用 DB 来避免闪烁,这实际上是由 requestAnimationFrame() 解决的。也许这篇关于 Offscreen-Rendering 的文章可能很有趣。在那里我回答了 OP 关于使用 Sprite Buffer 将缓冲的图像数据复制和粘贴到屏幕的问题
2021-03-29 19:33:17