Canvas在高分屏模糊的根本原因是物理像素与逻辑像素不匹配,需通过动态设置canvas物理尺寸、用ctx.scale()缩放绘图上下文、并对齐整数坐标三方面解决。

Canvas 在高分屏(如 Retina、2K/4K 显示器、高端手机)上模糊,根本原因是物理像素与逻辑像素不匹配——浏览器按 CSS 像素渲染 canvas 元素,但绘图缓冲区没同步放大,导致内容被拉伸插值。解决它不靠“修图”,而要从尺寸、坐标、缩放三方面对齐设备像素。
动态设置 canvas 物理尺寸并缩放绘图上下文
这是最核心、最通用的解法。关键不是改 CSS 大小,而是让 canvas.width 和 canvas.height 对应真实物理像素,并用 ctx.scale() 把绘图坐标系“复位”到开发者熟悉的 CSS 像素单位。
- 先获取设备像素比:
const dpr = window.devicePixelRatio || 1 - 用
getBoundingClientRect()获取 canvas 当前显示区域(CSS 像素宽高) - 设置 canvas 实际缓冲区尺寸:
canvas.width = rect.width * dpr,canvas.height = rect.height * dpr - 用 CSS 固定显示尺寸:
canvas.style.width = rect.width + 'px',canvas.style.height = rect.height + 'px' - 最后调用
ctx.scale(dpr, dpr),这样你画10, 10就真在 10×dpr 物理像素位置,线条和文字不会被插值模糊
确保绘制坐标为整数(避免亚像素渲染)
即使适配了 DPR,若绘图时用了 10.3、25.7 这类非整数坐标,浏览器仍会启动抗锯齿,把一个点颜色“摊开”到周围像素,造成虚边或发灰。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 画线、矩形、文字前,对关键坐标做取整:
Math.round(x * dpr) / dpr(缩放后坐标)或直接Math.round(x)(已 scale 后) - 特别注意表格线、网格、边框:循环绘制时,起始点和步长务必对齐像素,例如
for (let y = 0; y - 文字垂直居中时,
textBaseline = 'middle'配合y = Math.round(y),防止字体上下偏移半像素
文字与图像的额外优化
文字和图片对模糊更敏感,需单独处理:
立即学习“Java免费学习笔记(深入)”;
-
字体大小:设为
14 * dprpx 再通过ctx.scale()缩回,比直接用14px渲染清晰得多 -
禁用图片插值:如果用
drawImage()绘制图标或纹理,加上ctx.imageSmoothingEnabled = false,避免双线性缩放模糊 -
避免 transform 缩放 canvas 元素本身:用 CSS 的
transform: scale()会触发浏览器二次重采样,优先用ctx.scale()控制内部坐标系
响应式场景下的持续适配
窗口缩放、横竖屏切换、系统缩放比例变更(如 Windows 设置 125%)都会影响 DPR 或尺寸,不能只初始化一次。
- 监听
resize和orientationchange事件,重新执行尺寸调整逻辑 - 对频繁变化的场景(如图表拖拽),可节流处理,避免每帧都重设 canvas 尺寸
- 注意移动端键盘弹出可能触发 resize,建议加防抖或判断
innerHeight变化是否显著

















