为什么putImageData如此之慢?

我正在使用一个相对较大的画布,其中绘制了各种(复杂)的内容。然后,我想保存画布的状态,以便稍后可以快速将其重置为现在的状态。我使用getImageData进行此操作,并将数据存储在变量中。然后我在画布上再画一些东西,然后使用putImageData将画布重置为保存状态时的位置

然而,事实证明,putImageData非常慢。事实上,它比从头开始简单地重新绘制整个画布要慢,这涉及到覆盖大部分表面的几个drawImage,以及超过40000个lineTo操作,然后是笔划和填充

使用putImageData从头开始重新绘制约2000 x 5000像素的画布需要约170ms,但需要高达240ms的时间。为什么putImageData与重画画布相比速度如此之慢,尽管重画画布涉及使用drawImage填充几乎整个画布,然后使用lineTo、stroke和fill再次使用多边形填充大约50%的画布。因此,基本上,在重画时,每个像素都至少接触一次

因为drawImage似乎比putImageData快得多(毕竟,重画画布的drawImage部分所需时间不到30毫秒)。我决定不使用getImageData来保存画布的状态,而是使用canvas.toDataURL,然后从数据URL创建一个图像,我会将该图像粘贴到drawImage以将其绘制到画布上。事实证明,整个过程要快得多,只需要大约35毫秒就可以完成

那么,为什么putImageData比备选方案(使用getDataURL或简单地重画)慢得多呢?我怎样才能进一步加快速度?是否存在以及如果存在,通常存储画布状态的最佳方法是什么

(所有数字都是使用Firefox中的Firebug进行测量的)

只是一个小的更新什么是最好的方法是这样做。实际上,我写了一篇关于高性能ECMAScript和HTML5画布(pdf,德语;密码:stackoverflow)的学士论文,所以我现在已经积累了一些关于这个主题的专业知识。显然,最好的解决方案是使用多个画布元素。从一个画布绘制到另一个画布的速度与将任意图像绘制到画布的速度一样快。因此”;储存;画布的状态与稍后使用两个画布元素时再次恢复画布的速度一样快

这个jsPerf测试用例非常清楚地显示了各种方法及其优缺点

为了完整起见,这里是您真正应该如何做的:

//设置
var buffer=document.createElement('canvas');
buffer.width=canvas.width;
buffer.height=canvas.height;
//拯救
buffer.getContext('2d').drawImage(画布,0,0);
//恢复
canvas.getContext('2d').drawImage(缓冲区,0,0);

根据浏览器的不同,此解决方案比获得升级票的解决方案快5000倍

发表评论