Firefox中Canvas旧动画残留问题排查与求助
Firefox下Canvas动画残留问题的处理方案
问题现象
Canvas动画在Chrome、Edge中运行正常,但在Firefox里会出现旧帧残留的情况:
原绘制代码
function draw() { c.height = canvas_height; c.width = canvas_width; // 先平移到画布中心再缩放,保证始终以当前视角为中心缩放 ctx.translate(div.offsetWidth / 2, div.offsetHeight / 2); ctx.scale(camera_zoom, camera_zoom); ctx.translate(-div.offsetWidth / 2 + camera_offset.x, -div.offsetHeight / 2 + camera_offset.y); ctx.clearRect(0, 0, div.offsetWidth, div.offsetHeight); draw_tree( font, top_individuals, tree, x_individuals, space_between_columns, space_between_rows ); requestAnimationFrame(draw); }
测试对比
- 含
clearRect的代码片段(Firefox中异常):
c.height = canvas_height; c.width = canvas_width; // 先平移到画布中心再缩放,保证始终以当前视角为中心缩放 ctx.translate(div.offsetWidth / 2, div.offsetHeight / 2); ctx.scale(camera_zoom, camera_zoom); ctx.translate(-div.offsetWidth / 2 + camera_offset.x, -div.offsetHeight / 2 + camera_offset.y); ctx.clearRect(0, 0, div.offsetWidth, div.offsetHeight);
- 移除
clearRect的代码片段(Firefox中正常):
c.height = canvas_height; c.width = canvas_width; // 先平移到画布中心再缩放,保证始终以当前视角为中心缩放 ctx.translate(div.offsetWidth / 2, div.offsetHeight / 2); ctx.scale(camera_zoom, camera_zoom); ctx.translate(-div.offsetWidth / 2 + camera_offset.x, -div.offsetHeight / 2 + camera_offset.y);
问题原因与解决方法
问题核心在于clearRect的调用时机:
- 你已经通过重置
c.height和c.width清空了画布,这一步操作本身会重置画布的所有状态,包括清空像素内容,所以clearRect属于重复操作。 - 在Firefox中,调用
translate和scale后,画布的变换矩阵已被修改,此时执行clearRect(0,0, div.offsetWidth, div.offsetHeight),实际清除的区域是经过变换后的局部区域,而非整个画布,导致旧帧内容残留。
针对Firefox的处理方式:
- 最简方案:直接移除
ctx.clearRect(0,0, div.offsetWidth, div.offsetHeight),仅保留重置画布尺寸的逻辑即可完成清空。 - 如需保留清除逻辑:先重置画布变换矩阵再执行清除,比如在
clearRect前添加ctx.setTransform(1, 0, 0, 1, 0, 0),确保清除范围是整个画布;或者用ctx.save()和ctx.restore()包裹变换操作,在清除前恢复初始状态。
内容的提问来源于stack exchange,提问作者Marcos Camargo
相关产品推荐
相关产品推荐

