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时),图形变粗、细节糊掉:
- 获取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,这会触发二次插值


















