canvas标签本身不渲染图形,仅提供可编程像素缓冲区;高性能依赖html属性设宽高(禁用css缩放)、缓存getcontext("2d")实例、手动局部重绘及离屏预渲染等可控机制。

canvas 标签本身不渲染任何图形,它只是提供一块像素级的、可编程的空白缓冲区。所谓“高性能绘图容器”,关键不在标签写法本身,而在于初始化方式是否规避了常见陷阱,以及后续是否能支撑高频重绘逻辑。
canvas 宽高必须用 HTML 属性设置,不能靠 CSS
这是最容易出问题的第一步。如果只写 style="width:800px;height:600px",浏览器会拉伸画布位图,导致所有坐标错乱、线条模糊、圆弧变形。
- ✅ 正确:
<canvas id="render" width="800" height="600"></canvas> - ❌ 错误:
<canvas id="render" style="width:800px;height:600px"></canvas> - 若需响应式缩放,应在 JS 中监听
resize事件,动态修改canvas.width和canvas.height属性(注意:不是 style),再调用重绘逻辑
getContext('2d') 是唯一绘图入口,且不可重复获取不同上下文
拿到 DOM 元素后,getContext('2d') 返回的 CanvasRenderingContext2D 实例,是你操作像素的全部接口。它不是“可选配件”,而是强制依赖。
- 同一个
<canvas></canvas>元素调用多次getContext('2d')会返回同一实例;但一旦调用过getContext('webgl'),再调用getContext('2d')将返回null - 不要在每次绘制前都重新获取
ctx,缓存一次即可 - 没有
ctx.redraw()或ctx.refresh()这类方法——所有视觉更新都靠你手动调用clearRect()+ 绘图 API 实现
高性能本质是“可控重绘”,不是“自动优化”
Canvas 没有图层、没有 DOM 更新机制、不记录路径历史。它的性能优势来自你完全掌控何时清空、画什么、画多大区域——但也意味着你必须自己管理脏区、分层、缓存。
- 高频动画中,避免无脑
ctx.clearRect(0, 0, width, height),改用ctx.clearRect(dirtyX, dirtyY, dirtyW, dirtyH)只清局部 - 静态背景和动态元素应拆到不同
<canvas></canvas>层,用 CSSposition: absolute叠加,避免重复绘制不变内容 - 反复使用的图形(如图标、粒子形状)预先画到离屏
canvas,用ctx.drawImage(offscreen, x, y)复制,比重走路径快得多
真正卡顿的地方,往往不是“怎么画”,而是“要不要画”和“画多大”。Canvas 的高性能不是开箱即得的,它把控制权交给你,也把责任一起交了过来——比如忘记清除上一帧残留、在循环里反复设置 ctx.fillStyle、或在 requestAnimationFrame 回调里做大量计算,这些才是实际项目中最常拖垮帧率的操作。











