Oct1a

Canvas绘制模糊问题

原因解析

首先我需要了解一个属性 devicePixelRatio 屏幕像素比

在高清显示屏出现之前,比如屏幕宽度为1000px 那么其宽度上的物理像素也是1000px,而在高清屏出现之后,屏幕宽度为 1000px 时,物理像素有可能达到 2000px 或者更高

为了方便查询物理像素和屏幕像素的比值,在 window 对象上增加了一个属性 devicePixelRatio 来表示这个比值。

比如在 devicePixelRatio 为2的设备上,当我们使用 CSS 绘制一条 1px 的线时,为了保证绘制的大小,物理像素实际上会使用 2px 来绘制这一条线,而这样的转换是浏览器自动处理的,所以对开发者来说并没有太大的困扰

那么上面既然说了浏览器在渲染的时候会自动处理像素比的问题,CSS 绘制的图像经过转换之后不会出现模糊的问题,但 canvas 上怎么就出现了呢?

因为在 canvas 标签上定义的 widthheight 的值并不会被转换,100px 就会被渲染成 100px 的物理像素,但是设备要求的是 200px,这时浏览器只能智能地填充像素之间的空白,以适应要求的大小。这就是 canvas 绘制的图片出现模糊的原因

解决方案

  • 第一步:获取像素比
  • 第二步:将 canvas 标签上的宽高属性设置为 显示大小 * 像素比
  • 第三步:将 canvas 样式宽高设置为 显示大小
  • 第四步:使用 scale 方法设置比值
  • 第五步:绘制 canvas 图形
function createHDCanvas (canvas, w, h) {
  const ratio = window.devicePixelRatio || 1;
  canvas.width = w * ratio; // 实际渲染像素
  canvas.height = h * ratio; // 实际渲染像素
  canvas.style.width = `${w}px`; // 控制显示大小
  canvas.style.height = `${h}px`; // 控制显示大小
  const ctx = canvas.getContext('2d')
  ctx.scale(ratio, ratio)
  // canvas 绘制
  return canvas;
}

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。