canvas绘图效果取决于精确的状态控制与细节处理:需正确使用save()/restore()、beginpath(),重置fillstyle等状态;drawimage()须等待onload;动画应局部清除与复用资源;高清屏需按dpr缩放canvas像素。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

Canvas 绘图不是靠“炫酷”堆出来的,而是靠 getContext('2d') 后每一步的坐标、状态、绘制顺序控制出来的——写错一个 save()/restore() 或漏掉 beginPath(),图形就莫名消失或重叠。
为什么 fillRect() 没反应?常见状态残留问题
Canvas 是状态机,不是声明式绘图。上一次调用 strokeStyle 或 globalAlpha 会一直生效,直到你显式改掉它。
-
fillRect()看不见,大概率是fillStyle被设成了透明色(比如'rgba(0,0,0,0)')或不可见颜色(如'#fff'在白底上) - 如果之前调用了
stroke()但没清空路径,再调fillRect()可能触发意外描边(因为fill()也会作用于当前路径) - 最稳妥做法:每次绘制前手动重置关键状态:
ctx.fillStyle = '#000'; ctx.strokeStyle = '#000'; ctx.globalAlpha = 1;
drawImage() 图片不显示?异步加载没等完
drawImage() 不会自动等图片加载完成。直接 new Image() 后立刻画,img.width 还是 0,Canvas 就画了个空。
- 必须监听
img.onload回调,在里面调用drawImage() - 如果图片来自 URL,注意跨域问题:服务端没配
CORS头,或没加img.crossOrigin = 'anonymous',会导致drawImage()静默失败 + 后续toDataURL()报SecurityError - 避免重复创建
Image实例:图片可复用,加载完成后再传给多个 Canvas
动画卡顿?别在 requestAnimationFrame() 里反复 clearRect() + 重绘全屏
全量清除再重画看似简单,但对大 Canvas 或高频帧率(60fps)很吃资源,尤其在移动端。
立即学习“前端免费学习笔记(深入)”;
- 只清除真正需要更新的区域:
ctx.clearRect(x, y, width, height),比全屏clearRect(0,0,w,h)快得多 - 如果只是平移/缩放一个元素,考虑用
transform(ctx.setTransform())+ 局部重绘,而不是清全屏 - 避免在动画循环里新建对象(如每次 new Path2D()、重复解析字符串颜色),提前创建、复用
导出图片模糊?Canvas 像素比没对齐设备 dpr
高清屏(dpr > 1)下,Canvas 的 CSS 尺寸和实际像素尺寸不一致,直接 toDataURL() 会拉伸模糊。
- 获取设备像素比:
const dpr = window.devicePixelRatio || 1; - 设置 Canvas 实际宽高为 CSS 宽高的 dpr 倍:
canvas.width = canvas.clientWidth * dpr;,再用ctx.scale(dpr, dpr)缩放坐标系 - 注意:
scale()会影响所有后续绘制(包括文字大小、线宽),需同步调整或用save()/restore()包裹
Canvas 的“炫酷”藏在细节里:路径是否闭合、状态是否隔离、像素是否对齐、资源是否预加载——这些地方一松懈,效果就打折,而且很难一眼看出哪行代码惹的祸。











