根本原因是canvas物理像素未匹配设备像素比(dpr),导致浏览器插值缩放而模糊;需动态设置canvas的width/height为css尺寸×dpr,用style固定显示尺寸,并调用ctx.scale(dpr,dpr)适配坐标系。

Canvas 在 Retina 屏上模糊,根本原因是画布的物理像素(device pixel)没跟上屏幕的设备像素比(dpr)。浏览器按 CSS 像素渲染时,把 1 个 CSS 像素拉伸成多个物理像素显示,而 canvas 的 width 和 height 默认只按 1:1 设置,导致绘制内容被插值放大、线条变粗、边缘发虚。
正确设置 canvas 的内在分辨率
关键不是改 style,而是动态匹配设备像素比(window.devicePixelRatio)重设 canvas 的 width 和 height 属性:
- 先读取
devicePixelRatio(如 iPhone 14 是 3,MacBook Pro 视网膜屏常见为 2) - 将 canvas 的
width和height设为原始CSS尺寸 × dpr - 再用 CSS 把 canvas 的
style.width和style.height固定回原始尺寸(比如 400×300px),强制缩放到视觉大小 - 最后在绘图前,对 2D 上下文做
ctx.scale(dpr, dpr),让所有坐标单位自动适配高分采样
避免抗锯齿干扰清晰度
默认开启的抗锯齿会让线条边缘过渡柔和,在高分屏上反而削弱锐利感。可针对性关闭:
-
ctx.imageSmoothingEnabled = false(禁用图片缩放插值) -
ctx.lineCap = 'butt'和ctx.lineJoin = 'miter'减少端点/转角模糊 - 绘制单像素线时,确保坐标落在整数位置(如
ctx.fillRect(10.5, 20.5, 1, 1)比10, 20更锐利)
配合视口与初始化时机
Canvas 适配必须和页面整体响应逻辑对齐:
- 确保
<meta name="viewport" content="width=device-width, initial-scale=1.0">已设置,防止 iOS 强制缩放破坏 dpr 判断 - 在
window.addEventListener('resize', ...)中重新计算并重置 canvas 尺寸,尤其处理横竖屏切换 - 首次渲染前执行一次 dpr 适配,不要依赖 onload 或 DOMContentLoaded 的延迟——有些设备 dpr 值需主动触发才稳定
使用 Fabric.js 等封装库时的注意事项
像 Fabric.js 这类高级 canvas 库已内置部分 dpr 支持,但需显式启用:
- 创建实例时传入
enableRetinaScaling: true - 确认其
canvas.getElement().style.width和canvas.getElement().width符合上述比例关系 - 自定义滤镜或离屏渲染(offscreen canvas)时,仍要手动处理 dpr 缩放,库不会自动透传
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











