最近又写了个canvas,发现绘制的界面文字有点糊,因为我使用的是4k的外接屏幕,所以是以前开发的时候没感觉,现在有感觉了。。。
原因
为啥模糊呢?我们可以把canvas渲染出的东西其实就是绘制的一张图片,不是矢量图,是位图。高dpi显示设备意味着每平方英寸有更多的像素。比如2k屏,浏览器就会以2个像素点来渲染一个像素。该canvas在Retina(视网膜)屏幕上相当于占据了2倍的空间,相当于图片被放大了一倍,因此绘制出来的文字会变得模糊。
解决思路
在canvas的context
中存在一个backingStorePixelRatio
的属性,但是目前来看已经废弃了,所以也没必要去了解了。
我们可以使用window.devicePixelRatio
来查询设备的dpi
。这个方法返回当前显示设备的物理像素分辨率与css像素分辨率之比。也可以理解为一个css像素的大小与一个物理像素的大小的比率。简单来说,它告诉浏览器应该使用多少屏幕实际像素来绘制单个css像素。
ps:当用户拖动浏览器到别的屏幕时,可以使用window.matchMedia()
来检查devicePixelRatio
的值是否发生改变。
具体可以查看MDN window.devicePixelRatio
因此,我们的方案是,获得设备的dpi(像素比),然后将canvas放大到该设备像素比来绘制,然后用css压缩到原来大小,即可显示高清图像。
开干!
准备一个id为canvas
的dom:
1 | <canvas id="canvas" width="800" height="200"></canvas> |
获取context
:
1 | const canvasEl = document.getElementById('canvas') |
获取dpi的函数,如果window.devicePixelRatio
获取失败就返回1:
1 | function getDpi() { |
设置canvas大小的方法:
1 | function setCanvasWidth(canvasEl, ratio) { |
这里使用了全局变量保存了原始的canvas的大小,这是为了在绘制的时候需要计算canvas大小的时候方便一点。
绘制:
1 | function draw(canvasEl, content) { |
最后开始调用这些方法:
1 | var ratio = getDpi() |
需要注意的是,我们最后使用context.scale(ratio, ratio)
来对canvas进行了缩放。才最终实现了我们的目的。
最后看下结果: