比仅仅部分更快地清除整个画布?

时间:2013-09-10 12:39:40

标签: javascript animation canvas html5-canvas

注意到在Canvas中使用动画时我没想到的东西。我有一个相当简单的动画,五个不同大小的图像在一个循环中从屏幕的底部到顶部移动。

我将所有图像数据放在一个数组中,然后通过循环将它们绘制到画布上,然后使用window.requestAnimationFrame在下一帧上进行新的绘制。

这是有趣的部分,起初我只是为使用context.clearRect(0, 0, canvas.width, canvas.height);渲染的每个帧清除了画布。然后我认为这必然是浪费计算,为每个渲染清除整个画布,即使你只有部分屏幕实际发生了变化。

所以我重写了清除画布的部分只清除旧图像绘制的痕迹,使用类似的东西:

for (var key in _images) {
   context.clearRect(_images[key].x-1, _images[key].y+_images[key].height, _images[key].width+2, 5);
}

但令我惊讶的是,这似乎更慢......首先我的帧率为49-60,然后是47-57。知道为什么?还有其他方法来优化这个吗?

2 个答案:

答案 0 :(得分:2)

0)我宁愿写:

for (var i=0, len=_images.length; i<len; i++) {
   var thisImage = _images[i];
   context.clearRect(thisImage.x, thisImage.y, thisImage.width, thisImage.height);
}

1)当requestAnimationFrame触发时,在更新前绘制,这样你就可以与屏幕同步了 2)将坐标四舍五入到最接近的64位,即在每个x坐标上使用&amp;(~3)可以加快速度。
3)你可以将一些clearRect组合在一起(=所有子弹/平铺的水平地板......) 4)我认为这里的主要问题是这些方法的开销 我做了一个jsperf知道更多:
http://jsperf.com/overhead-of-fillrect-and-clearrect/2

!!在测试过程中一定要看到帆布!!

结果:

Firefox ,clearRect的开销非常小,时间似乎也是如此 与像素数几乎成比例。 fillRect比较慢60%,看起来也很相称 面积覆盖。

64位Unalignment似乎没有在clearRect上有效,它使得表现 在fillRect上严重崩溃。

有些时候来自jsPerf(精度是如此):

全屏clearRect的208ns
55ns用于半屏clearRect - &gt; 4次使220ns vs 208
季度屏幕清晰度为13ns - &gt; 16次使208(!!!)

588ns全屏fillRect
1290ns半屏fillRect - &gt; 4次使1160
41ns四分屏幕填充 - &gt; 16次使656.

Safari ,所有结果都完全相同,除非有 更多开销:绘制4倍的点数只需要快3倍。

我知道精度是如此,但似乎在Firefox上 和Safari,结论是:
您清除屏幕的部分越少,删除的速度就越快

  • 并且更喜欢clearRect to fillRect -

Chrome :(日期05/14)fillRect比clearRect快得多。

IE11 :fillRect和clearRect名列前茅。

((如果有人可以在其他浏览器上看到,我会编辑 - 当我有时间 - ))

(假设你的图像是4像素对齐,代码是 64 align is:

for (var i=0, len=_images.length; i<len; i++) {
   var thisImage = _images[i];
   var x = thisImage.x ;
   context.clearRect(x & (~3), thisImage.y, thisImage.width + ((x&3)&&(16-(x&3))), thisImage.height);
}

答案 1 :(得分:0)

由于人们在评论中回答,我觉得他们覆盖了我的问题。这是一个夏日:

每个clearRect()占用的时间大致相同,因此最好少于几个。

要优化,应计算需要清除的区域,如果不是100%,则清除该区域。