javascript - 清除整个 Canvas 比清除部分更快?

标签 javascript animation canvas html5-canvas

在 Canvas 中玩动画时注意到了一些我没有预料到的事情。我有一个相当简单的动画,其中五个不同尺寸的图像循环地从屏幕底部移动到顶部。

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

这是有趣的部分,首先我只是清除了使用 context.clearRect(0, 0, canvas.width, canvas.height); 渲染的每个帧的 Canvas 。然后我想这肯定是浪费计算,为每个渲染清除整个 Canvas ,即使实际上只改变了屏幕的一部分。

所以我重写了清除 Canvas 的部分,仅清除旧图像绘制的痕迹,使用如下内容:

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

最佳答案

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

!!测试期间一定要看到 Canvas !!

结果:

Firefox,clearRect的开销很小,时间似乎 几乎与像素数成正比。 fillRect 慢了大约 60%,而且看起来也很成比例 覆盖区域。

64位未对齐似乎对clearRect没有影响,它提高了性能 严重落在 fillRect 上。

有时来自 jsPerf(精度一般):

全屏clearRect需要208ns
半屏 ClearRect 为 55 纳秒 -> 4 倍为 220 纳秒与 208 纳秒
四分之一屏幕clearRect需要13ns -> 16倍等于208(!!!)

588ns 全屏 fillRect
1290ns 半屏 fillRect --> 4 倍等于 1160
41ns 四分之一屏幕 fillrect --> 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);
}

)

关于javascript - 清除整个 Canvas 比清除部分更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18719229/

相关文章:

c# - 可以通过在WPF中平滑地改变字体粗细来脉冲文本吗?

c# - 如何通过几个点绘制贝塞尔曲线?

html - 删除 Canvas 元素下的空间?

javascript - Array.prototype.map()方法添加信息窗口

javascript - 可复用的JS函数

javascript - 用纯 Javascript 读取复杂的 JSON

javascript - Three.js:如何在缩放时更新 3D 散点图上点的颜色?

android - 如何做 Canvas 路径动画?

ios - 如何用动画将矩形变为圆形

android - 按轴计算 Canvas 中的点坐标