Fork me on GitHub

canvas高清屏中绘制模糊问题

用canvas绘制价格趋势图的时候发现在mac上看线条和文字都非常模糊

为什么?

因为 canvas 不是矢量图,而是像图片一样是位图模式的。高 dpi 显示设备意味着每平方英寸有更多的像素。也就是说二倍屏,浏览器就会以2个像素点的宽度来渲染一个像素,该 canvas 在 Retina 屏幕下相当于占据了2倍的空间,相当于图片被放大了一倍,因此绘制出来的图片文字等会变模糊。

因此,要做 Retina 屏适配,关键是知道当前屏幕的设备像素比,然后将 canvas 放大到该设备像素比来绘制,然后将 canvas 压缩到一倍来展示。

解决思路

浏览器的 window 对象中有一个 devicePixelRatio的属性,该属性表示了屏幕的设备像素比,即用几个(通常是2个)像素点宽度来渲染1个像素。

举例来说,假设devicePixelRatio的值为2 ,一张 100×100 像素大小的图片,在 Retina 屏幕下,会用 2 个像素点的宽度去渲染图片的 1 个像素点,因此该图片在 Retina 屏幕上实际会占据 200×200 像素的空间,相当于图片被放大了一倍,因此图片会变得模糊。

类似的,在 canvas context 中也存在一个 backingStorePixelRatio 的属性,该属性的值决定了浏览器在渲染canvas之前会用几个像素来来存储画布信息。 backingStorePixelRatio 属性在各浏览器厂商的获取方式不一样,所以需要加上浏览器前缀来实现兼容。

解决问题

1.首先获取canvas对象:

1
2
const paint = document.getElementById('graphic-canvas');
const ctx = paint.getContext('2d');

2.获取像素比,将 Canvas 宽高进行放大,放大比例为:devicePixelRatio / webkitBackingStorePixelRatio , 我们写了一个兼容的方法。

1
2
3
4
5
6
7
8
9
10
 const getPixelRatio = function (context) {
const backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
}
const ratio = this.getPixelRatio(ctx);

3.按实际渲染倍率来缩放canvas。
⚠️注意:

  • 要设置canvas的画布大小,使用的是 canvas.width 和 canvas.height;
  • 要设置画布的实际渲染大小,使用的 style 属性或CSS设置的 width 和height,只是简单的对画布进行缩放。

例如2倍屏幕下代码实例:

1
<canvas width="640" height="800" style="width:320px; height:400px"></canvas>

canvas画布大小是640px × 800px,但是实际渲染到页面的大小是320px × 400px,相当于缩小一倍来显示。

3倍屏幕下就是:

1
<canvas width="960" height="1200" style="width:320px; height:400px"></canvas>

因此,要使canvas适配高倍屏,就是要将canvas画布放大到设备像素比来绘制,最后将canvas压缩成一倍的物理大小来展示。如下:

1
2
3
4
paint.style.width = paint.width + 'px';
paint.style.height = paint.height + 'px';
paint.width = paint.width * ratio;
paint.height = paint.height * ratio;

4.绘制

由于 Canvas 放大后,相应的绘制图片时也要放大,有两种方式:

第一种方法:每一个绘制相应的放大,比较繁琐

1
ctx.fillText("我是清晰的文字", 50*ratio, 50*ratio);// 坐标位置乘以像素比

推荐第二种方法,scale方法

1
ctx.scale(ratio, ratio);

参考文章:https://www.html.cn/archives/9297

本文标题:canvas高清屏中绘制模糊问题

文章作者:tongtong

发布时间:2019年04月17日 - 20:04

最后更新:2019年04月18日 - 14:04

原始链接:https://ilove-coding.github.io/2019/04/17/canvas高清屏中绘制模糊问题/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束-------------