HTML5图表在Retina屏清晰显示的关键是全链路按devicePixelRatio对齐:canvas需同步设置width/height(物理像素)与style.width/style.height(CSS像素),并调用ctx.scale(dpr,dpr);字体、线宽、图片等均需适配dpr。

要让 HTML5 图表在 Retina 手机上清晰显示,关键不是“换张高清图”,而是让整个渲染链路按物理像素密度(dpr)对齐——从 canvas 缓冲区、绘图坐标系,到字体、边框、图像资源,全部按比例提升。
Canvas 必须同步设置 DOM 尺寸与 CSS 尺寸
90% 的模糊问题出在这里:只改了 canvas.style.width/height,却没动 canvas.width/canvas.height。
- DOM 属性(
width/height)决定绘图缓冲区分辨率,即实际绘制的像素数 - CSS 样式(
style.width/style.height)只控制它在页面上占多大空间 - 两者不一致 = 浏览器拉伸低清缓冲区 → 模糊、锯齿、线条变粗
正确初始化写法:
const dpr = window.devicePixelRatio || 1;
const width = 400; // 设计宽度(CSS 像素)
const height = 250;
<p>canvas.width = Math.floor(width <em> dpr);
canvas.height = Math.floor(height </em> dpr);
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';</p><p>const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr); // 后续所有绘图坐标无需手动乘 dpr
图表文字和线条需适配 dpr 缩放
即使 canvas 缓冲区正确,若字体大小、线宽仍用固定 px 值,也会在高分屏下显得过细或发虚。
立即学习“前端免费学习笔记(深入)”;
- 字体建议用
ctx.font = '14px sans-serif',再配合ctx.scale(dpr, dpr),自动放大渲染 - 避免写死
ctx.lineWidth = 1;可设为ctx.lineWidth = 1 * dpr或统一 scale 后保持逻辑值为 1 - 监听
resize和orientationchange,iOS 旋转后布局重排但 dpr 不变,需重新计算尺寸并重绘
图表中嵌入的图片/图标也要响应 dpr
如果图表里用了 <img>(如图例图标、背景水印)或 CSS 背景图,必须单独适配:
-
<img>标签优先用srcset:<img src="icon-24.png" srcset="icon-24.png 1x, icon-48.png 2x"> - 若用 CSS
background-image(如工具栏按钮),可用image-set(),但必须配background-size和固定容器尺寸:background-image: image-set(url(icon-24.png) 1x, url(icon-48.png) 2x);<br>background-size: 24px 24px;<br>width: 24px; height: 24px;
- 注意兼容性:
image-set()在 Firefox 中不支持,Safari 15.0–15.3 存在静默失效,建议加@supports降级
导出为图片时保留高清质量
用户点击“保存图表”时,若用 html-to-image 等库导出,需显式传入 dpr 参数:
- 确保库内部调用 canvas 时已按 dpr 放大缓冲区
- 部分库(如
html-to-image)默认启用pixelRatio: window.devicePixelRatio,但需确认版本 ≥ 2.0 - 导出前可临时将图表容器缩放至 2x 尺寸再截图,但更稳妥的是直接操作 canvas 缓冲区重绘



















