canvas高分屏模糊需按dpr重设物理尺寸并缩放坐标系:设canvas.width/height为css宽高×dpr,css宽高复原,ctx.scale(dpr,dpr),坐标宽高取整,禁用imagesmoothing和优化textrendering。

Canvas在高分屏上模糊,本质是物理像素和逻辑像素没对齐。不是画得不够好,而是画布“底子”没铺准——绘图分辨率没随设备像素比(DPR)放大,浏览器只能靠插值拉伸,一拉就虚。
按DPR重设画布物理尺寸
关键不是改CSS大小,而是让canvas.width和canvas.height真正反映设备能显示的物理像素数:
- 用
canvas.getBoundingClientRect()获取当前CSS布局宽高 - 取
window.devicePixelRatio || 1,得到真实DPR - 设
canvas.width = rect.width * dpr、canvas.height = rect.height * dpr - 再用CSS把显示尺寸压回原样:
canvas.style.width = rect.width + 'px'
缩放绘图坐标系,保持逻辑习惯
光调大画布还不够。如果不缩放上下文,你画一个fillRect(0,0,100,100),实际会占200×200物理像素(DPR=2时),图形变粗、细节糊掉:
用户要生成可打印的中文字帖/练习纸、导出多页 A4 PDF 报告,或把 SVG 设计稿零误差还原到 Canvas 时使用。本技能是「Canvas 内容工厂闭环」的总控,编排:网格渲染引擎(13 种教育网格+拼音标注) → 多页 PDF 导出(A4 合成) → SVG 精准复刻(坐标误差<0.001px)。触发词:生成字帖、练习纸、导出 PDF、SVG 转 Canvas、印刷级还原、A4 报告、米字格田字格。
- 获取2D上下文后,立刻执行
ctx.scale(dpr, dpr) - 此后所有坐标、宽高都按CSS像素写,不用手动乘DPR
- 比如想画1px线,仍用
ctx.lineWidth = 1,而不是设成2
坐标准确到整数像素
哪怕DPR适配正确,若坐标带小数(如x=10.3),浏览器会做亚像素渲染,边缘自动柔化:
- 绘制前对关键坐标取整:
Math.round(x)、Math.floor(y) - 矩形宽高、线条宽度也建议取整,避免
lineWidth = 1.5这类值 - 文字绘制时,配合
textBaseline = 'top'和textAlign = 'left',再对基点取整
关掉干扰渲染的默认行为
Canvas自带的平滑和抗锯齿,在清晰度优先场景下反而是累赘:
- 禁用图像缩放平滑:
ctx.imageSmoothingEnabled = false - 优化文字渲染:
ctx.textRendering = 'optimizeLegibility'或'geometricPrecision' - 避免用CSS
transform: scale()或zoom缩放整个Canvas,这会触发二次插值










