Canvas绘制的图片为什么模糊不清?

Mr.晨羲 阅读 46

我在用 Canvas 绘制一张 200×200 的 PNG 图片,但显示出来特别模糊,明明原图是清晰的。是不是我哪里设置错了?

我试过直接用 ctx.drawImage(img, 0, 0),也试过指定宽高 ctx.drawImage(img, 0, 0, 200, 200),结果都一样糊。网上有人说要处理设备像素比,但我照着改了还是没用。

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.src = 'icon.png';
img.onload = () => {
  ctx.drawImage(img, 0, 0, 200, 200);
};
我来解答 赞 7 收藏
二维码
手机扫码查看
2 条解答
程序猿贝贝
啊,这个经典问题!canvas图片模糊90%都是设备像素比(devicePixelRatio)的锅。你的代码其实没大问题,只是没考虑高DPI屏幕。

试试这样优化一下:

1. 先获取设备像素比:
const dpr = window.devicePixelRatio || 1;

2. 设置canvas的实际尺寸和显示尺寸:
const canvas = document.getElementById('myCanvas');
canvas.style.width = '200px';
canvas.style.height = '200px';
canvas.width = 200 * dpr;
canvas.height = 200 * dpr;

3. 绘图时别忘了缩放context:
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);

4. 最后画图:
img.onload = () => {
ctx.drawImage(img, 0, 0, 200, 200);
};

这样处理后,在Retina屏上也不会糊了。原理很简单:canvas的实际分辨率是显示分辨率的dpr倍,然后用CSS控制显示大小。我之前在移动端项目被这个坑过好多次...
点赞 1
2026-03-07 22:07
上官东慧
这个问题在 Canvas 开发里太常见了,核心原因就在于 Canvas 的内部分辨率(width/height 属性)和 CSS 显示尺寸不一致,导致浏览器做了插值拉伸。MDN 上关于 Canvas 的 HiDPI 支持有专门说明,虽然有点繁琐,但这是标准解法。

你说试过处理 DPR 还是糊,多半是因为只改了 canvas 的物理像素大小,忘了用 ctx.scale 缩放绘图上下文。如果不缩放,你画的图依然会被拉伸到新的物理像素上,反而更糊或者位置不对。

推荐的做法是完整走一遍这套流程:先拿 window.devicePixelRatio,把 canvas 的属性宽高设为 CSS 宽高乘以 DPR,然后一定要调用 ctx.scale(dpr, dpr) 把坐标系放大,之后你再用 drawImage 绘制 200x200 的尺寸,它就能在高清屏上 1:1 对应物理像素了。

代码给你写好了,直接替换就能用:

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;

// 1. 设置 CSS 样式尺寸(逻辑像素)
canvas.style.width = '200px';
canvas.style.height = '200px';

// 2. 设置 Canvas 属性尺寸(物理像素)
canvas.width = 200 * dpr;
canvas.height = 200 * dpr;

// 3. 缩放绘图上下文,使绘图操作使用逻辑像素单位
ctx.scale(dpr, dpr);

const img = new Image();
img.src = 'icon.png';
img.onload = () => {
// 这里依然写逻辑尺寸 200
ctx.drawImage(img, 0, 0, 200, 200);
};


如果这样改完还是糊,那就得去查一下那张 icon.png 本身是不是在高清屏上就糊了,或者是浏览器缩放比例的问题,但大概率是上面这个 scale 没加。
点赞 4
2026-03-04 02:00