canvas图形重绘优化的核心是只处理变化的“脏区”,通过精准标记边界、用clearrect精确擦除、分层离屏缓存及适配css缩放来提升性能。

Canvas图形重绘优化的核心,是避免全量清空和重绘,转而只处理真正变化的区域——也就是“脏区”。这不仅能显著降低GPU填充开销,还能提升高刷新率或大画布场景下的帧率稳定性。
精准标记脏区边界
每次图形状态变更(如位置移动、尺寸缩放、颜色更新),不要立刻绘制,而是先计算它影响的最小包围矩形(Bounding Box):
- 例如一个半径10的圆从(50, 50)移到(80, 60),脏区左上角为(40, 40),右下角为(90, 70)
- 多个变化区域可用Math.min和Math.max合并成一个联合矩形
- 维护一个全局dirtyRect = {x, y, width, height}对象,每次调用markDirty(x, y, w, h)更新它
- 坐标建议做Math.floor()对齐,防止亚像素清除引发抗锯齿异常
用clearRect精确擦除,不碰其他内容
clearRect()是浏览器原生实现,比fillRect()填色或重绘背景快得多:
- 只清除脏区:ctx.clearRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height)
- 避免clearRect(0, 0, canvas.width, canvas.height)——这是性能杀手
- 若脏区内有阴影、半透明叠加等混合效果,单纯clearRect可能破坏视觉,此时应改用离屏缓存+合成策略
- 清除前检查区域是否在画布可视范围内,跳过无效调用
分层+离屏缓存静态内容
把不变或低频变化的部分(如网格背景、UI边框、底图)抽离到离屏Canvas中:
- 创建const offscreen = document.createElement('canvas'),尺寸与主Canvas一致
- 首次将静态内容绘入offscreen,主Canvas用drawImage(offscreen, 0, 0)贴一次
- 后续只需在主Canvas上清除并重绘动态部分,完全跳过背景重复绘制
- 适合粒子系统、实时仪表盘指针等高频变化区域
注意CSS缩放与坐标系一致性
当Canvas被CSS缩放(如transform: scale(2))时,clearRect仍按逻辑像素计算,容易导致清除偏移或模糊:
- 确保canvas.width / canvas.height与CSS设置的宽高一致
- 或按window.devicePixelRatio调整Canvas内部尺寸
- 清除前可用ctx.save() + ctx.scale()统一坐标系,清除后再restore()
- 调试时可临时关闭CSS缩放,确认清除位置是否准确











