Canvas 高清屏模糊主因是物理像素未对齐,需检查 devicePixelRatio 是否动态响应、canvas 三尺寸(width/height/style)是否同步乘 effectiveDPR、绘图坐标是否取整及图像资源是否高分适配。

Canvas 在高清屏上模糊,不是画布“画得差”,而是物理像素没对齐。排查要从设备像素比(dpr)是否真正生效、三个关键尺寸是否同步、绘图坐标是否取整这三方面入手。
检查 devicePixelRatio 是否被正确读取和响应
很多模糊问题其实卡在第一步:dpr 拿错了或没更新。
- 别只在页面加载时读一次
window.devicePixelRatio,用户切换显示器、调整系统缩放(如 Windows 从 100% 改为 125%)时,dpr 会变,但 resize 事件不触发——必须监听matchMedia('(resolution)') - 验证 dpr 值是否真实:打开 Chrome DevTools → Rendering → 启用 “Emulate DPR”,设为 2 或 3,再执行
console.log(window.devicePixelRatio),确认输出与模拟值一致 - 注意
backingStorePixelRatio干扰:某些浏览器(如旧版 Safari)的绘图缓冲区比例和设备比例不一致,要用effectiveDPR = window.devicePixelRatio / (ctx.backingStorePixelRatio || 1)校正
核对 canvas.width / canvas.height 与 CSS 尺寸是否严格匹配
这是最常出错的环节:只改一边,等于白做。
-
canvas.width和canvas.height必须基于getBoundingClientRect()获取的 CSS 像素尺寸 × effectiveDPR,不能用父容器 offsetWidth/offsetHeight(它们可能受 box-sizing、border、margin 影响) -
canvas.style.width和canvas.style.height必须显式设为带单位的 px 值(如"300px"),不能留空、不能设为"100%"或依赖继承——否则浏览器按默认行为渲染,导致拉伸 - 用开发者工具 Elements 面板直接查看 canvas 元素:对比 computed 的 width/height(CSS 显示尺寸)和属性面板里的 width/height(内部缓冲区尺寸),二者比值应等于 effectiveDPR
确认绘图上下文是否完成坐标系重校准
即使尺寸全对,漏掉这步,图形也会偏移、缩小、发虚。
立即学习“前端免费学习笔记(深入)”;
- 必须调用
ctx.setTransform(effectiveDPR, 0, 0, effectiveDPR, 0, 0)(推荐)或ctx.scale(effectiveDPR, effectiveDPR);仅用scale()有叠加风险,setTransform()更干净 - 校准后,所有绘图 API(
fillRect、strokeText、drawImage)都应使用逻辑像素坐标(即设计稿尺寸),不再手动乘 dpr;如果还写了x * dpr,就是双重缩放,线条变粗、文字糊成块 - 绘制 1px 线条或小字号文字时,确保传入的 x/y 是整数:
ctx.fillRect(Math.round(x), Math.round(y), w, h);亚像素坐标(如 y=20.3)会强制浏览器插值,边缘立刻毛边
验证图像资源本身是否适配高分屏
Canvas 再清晰,画进去的是低分图,结果还是糊。
- 用
drawImage加载图片前,检查该图片是否提供 @2x/@3x 版本;优先用<img>+srcset加载,再转成 Canvas 图像源 - 避免直接用
new Image()加载未适配的 URL;若必须动态加载,按 dpr 选择路径:const src = `icon-${Math.round(dpr)}x.png` - 加载完成后,用
image.naturalWidth和canvas.width对比:若 naturalWidth 远小于 canvas.width(比如图宽 200px,canvas 缓冲区宽 600px),说明图被拉伸,需换更高清版本



















