canvas在高清屏上模糊的主因是坐标未取整,浏览器对非整数坐标(如x=12.3)进行亚像素插值,导致图形摊开在多个物理像素上而边缘发虚;需对所有绘图坐标、尺寸、偏移统一用math.round()等取整,并配合devicepixelratio适配canvas物理尺寸与ctx.scale,确保整数坐标精准落在物理像素网格上。

Canvas在高清屏上模糊,一大主因是坐标没取整。浏览器对非整数坐标(比如 x=12.3、y=45.7)会自动做亚像素插值,把一个图形“摊”在多个物理像素上,结果就是边缘发虚、线条毛糙、小字糊成一片。
为什么非整数坐标会导致模糊
Canvas底层绘制依赖物理像素网格。当坐标不是整数时,浏览器无法精确落点,只能混合周围像素颜色来模拟过渡——这本是为抗锯齿设计的,但用在清晰线框或文字上反而适得其反。尤其在 DPR ≥ 2 的设备(如 MacBook Retina、主流安卓旗舰)上,这种模糊会被放大。
所有绘图操作前强制取整
不是只修起点,而是每个涉及位置、尺寸、偏移的数值都要校准:
-
基础图形:fillRect、strokeRect、arc、lineTo 的 x/y/w/h 全部用
Math.round()或Math.floor() -
文字定位:先设
ctx.textAlign = 'left'和ctx.textBaseline = 'top',再对fillText(text, x, y)中的 x/y 取整 -
线条宽度:避免
ctx.lineWidth = 1.5,统一用1、2这类整数 - 图像绘制:drawImage 的 sx/sy/sw/sh/dx/dy/dw/dh 同样需整数化,尤其 dx/dy 决定贴图落点
配合 DPR 适配效果更稳
单靠取整能改善很多,但若 canvas 物理尺寸没跟上设备像素密度,仍可能被浏览器二次缩放模糊。建议组合使用:
- 先按
window.devicePixelRatio设置 canvas.width/height - 再用
ctx.scale(dpr, dpr)维持逻辑坐标习惯 - 最后所有绘图参数统一取整——此时的“整数”对应真实物理像素,不漂移
避开常见陷阱
有些看似合理的写法,实际悄悄引入小数:
- 用百分比或 flex 布局计算 canvas 位置后直接赋值给绘图坐标(如
left * 0.8) - 动画中用 ease-in-out 等缓动函数生成坐标,未做最终取整
- 缩放 canvas 后未同步调整绘图坐标系,导致逻辑坐标失真











