高频动画中应只清除“脏矩形”而非整屏:记录并清除动画元素上一帧占据区域,配合分层(主体/ UI / 特效)与离屏绘制优化性能,注意坐标系、像素尺寸及状态隔离。

高频动画中,clearRect() 不是“清整个画布”就完事,关键在于只清真正需要更新的区域——也就是所谓“脏矩形”(dirty rectangle)。清得准,才能省掉大量像素操作,避免掉帧。
明确清除范围:只清变化区域,不碰静态内容
整屏 clearRect(0, 0, canvas.width, canvas.height) 在 1920×1080 或高 DPI 屏幕上,每帧要操作数百万像素,极易卡顿。正确做法是:
- 记录上一帧中被动画元素占据的矩形位置(x, y, width, height)
- 本帧绘制前,仅对该区域调用
clearRect() - 若动画对象移动了 5px,就只清旧位置 + 新位置两个矩形,或取并集作为单个清除区域
- 背景、UI 图标、文字等静止内容不参与清除,它们要么预先绘在离屏 canvas 上,要么靠分层逻辑避开重绘
配合图层分工,避免无意义清除
把画布逻辑拆成几层,每层用不同清理策略:
- 主体动画层(如小球、角色):每帧只清其上一帧所在矩形,再重绘新位置
-
UI 层(血条、计分板):每个组件维护自己的坐标和尺寸,变化时单独
clearRect()对应区域,再重填 -
特效层(粒子、闪光):可不用
clearRect,改用globalCompositeOperation = 'lighter'或逐帧降低透明度,让旧帧自然淡出
注意清除前提:尺寸、坐标、状态都得对得上
clearRect() 看似简单,但实际掉帧常因这些细节出错:
立即学习“前端免费学习笔记(深入)”;
- 确保传入的
width和height是 canvas 元素的 实际像素尺寸(即canvas.width/canvas.height),不是 CSS 设置的缩放尺寸 - 清除坐标基于 canvas 坐标系,若用了
ctx.translate()或ctx.scale(),需先ctx.setTransform(1, 0, 0, 1, 0, 0)重置,或手动反算坐标 -
clearRect()只清像素,不重置绘图状态(如globalAlpha、strokeStyle、transform),动画循环里记得用save()/restore()隔离状态,或显式重设
性能兜底建议:预加载 + 缓存 + 离屏绘制
清除只是优化一环,高频动画稳定还需配套措施:
- 所有图片资源必须提前
img.onload加载完成,禁止在动画循环里 new Image() - 重复使用的静态图形(如按钮、图标、背景块)先绘制到一个离屏
<canvas>,后续直接drawImage(offscreencanvas, ...)贴图,比逐点重绘快得多 - 用
requestAnimationFrame替代setInterval,保证与屏幕刷新率同步 - 在开发时打开浏览器的 Rendering 面板,勾选 “FPS Meter” 和 “Paint Flashing”,直观观察哪些区域被反复重绘或清除



















