canvas在高分屏下,绘制文字和线条都会出现模糊的现象。
本以为是因为canvas的功能性兼容性问题,进行查阅相关资料才知道是显示器的问题。具体原因参考这里
举个简单的栗子,在 iPhone3G 时代,屏幕宽度是 320px,其宽度上的物理像素也是 320px;而到了 4s 时代,屏幕宽度依然是 320px,但是宽度上的物理像素却变成了 640px,是宽度的两倍。屏幕宽度没变,物理像素却增加了,所以为了屏幕显示的内容不改变,原先需要一个像素绘制的点,现在会用两个像素来绘制。为了表示这种屏幕的特性,浏览器全局对象下就有了这样一个属性——devicePixelRatio
设备像素比,它的计算方式是 物理像素 / 屏幕宽度的像素,所以 3G 的设备像素比为 1 , 4s 为 2,而现在 iPhone 的 plus 型号手机的设备像素比为 3,甚至部分出现了比值为 4 的安卓设备。也是我们俗称的2k、3k、4k显示屏
当我们想要用canvas绘制一条 1px 的线时,由于当前浏览器的设备像素比是 2,所以实际上是通过 2 个像素点来绘制的。但是,canvas 绘图时,会从两个物理像素的中间位置开始绘制并向两边扩散 0.5 个物理像素。当设备像素比为 1 时,一个 1px 的线条实际上占据了两个物理像素(每个像素实际上只占一半),由于不存在 0.5 个像素,所以这两个像素本来不应该被绘制的部分也被绘制了,于是 1 物理像素的线条变成了 2 物理像素,视觉上就造成了模糊。
// 获取设备像素比
window.devicePixelRatio
说了那么多,下面是解决方案:
// devicePixelRatio = 2
// 在 2k 显示器上的demo,3k、4k进行自行换算
<style>
canvas {
width: 200px;
height: 200px;
}
</style>
<canvas id="canvas" width="400" height="400"></canvas>
其实本质原理就是:先放大 canvas画布放大,保证图片的展示保真度,再用 CSS 物理缩小,进行展示图片。
需要注意的是,要在绘制之前先放大绘图区域,否则无效