0

在 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。知道为什么吗?还有其他方法可以优化吗?

4

2 回答 2

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 坐标上使用 &(~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 半屏 clearRect
55ns -> 4 次 220ns vs 208
13ns 四分之一屏 clearRect -> 16 次 208 (!!!)

588ns 全屏
填充矩形 1290ns 半屏填充矩形 --> 4 次为 1160
41ns 四分之一屏填充矩形 --> 16 次为 656。

Safari,一切结果都差不多,只是开销更大:少画 4 倍的点只快 3 倍。

我知道精度一般,但似乎在 Firefox 和 Safari 上,结论是:
清除的屏幕部分越少,擦除的速度越快

  • 并且更喜欢 clearRect 到 fillRect -

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

IE11:fillRect 和 clearRect 相当。

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

(如果您的图像对齐 4 个像素,则 64 对齐的代码是:

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);
}

)

于 2013-09-11T23:01:36.643 回答
0

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

每个都clearRect()占用大致相同的时间,所以少比多好。

要进行优化,应该计算需要清除的区域(如果不是 100%)并清除它。

于 2013-09-11T06:55:06.103 回答