原因
因为 canvas 不是矢量图,而是像图片一样属于位图。高 dpi 显示设备意味着每平方英寸有更多的像素,比如说二倍屏,手机就会以2个像素点的宽度来渲染一个像素,该 canvas 在屏幕中相当于占据了2倍的空间,相当于绘制的元素被放大了一倍,因此绘制出来的图片文字等会变模糊。
解决方案思路
首先要明确一点,canvas分为画布尺寸和渲染尺寸。渲染尺寸就是在css样式文件里设置的width、height大小,而画布尺寸则是在canvas标签里设置的width和height,比如< canvas id=‘canvas’ width=“200” height=“200” />。
明确了什么是画布尺寸,什么是渲染尺寸。那么解决canvas在高清屏模糊的问题就很简单了,只需要将canvas的画布尺寸扩大到渲染尺寸的设备像素比倍,然后再缩放到渲染尺寸显示即可。举个例子,假如一个canvas的实际渲染尺寸大小为200x200px,那么在iPhone x手机DPR为3的情况下canvas的画布尺寸则为600*600,canvas绘制完毕后再缩放3倍显示即可。
效果图
优化前
优化后
代码
//设计稿宽度,一般为750const UI_Width = 750//同步获取设备系统信息const info = wx.getSystemInfoSync()//设备像素密度const dpr = info.pixelRatio;//计算比例const scale = info.screenWidth / UI_Width//计算canvas实际渲染尺寸let width = parseInt(scale * 335)let height = parseInt(scale * 299)//计算canvas画布尺寸let canvasWidth = width * dprlet canvasHeight = height * dpr//绘制canvasdrawCurrent(data) {const ctx = wx.createCanvasContext('canvas');//根据像素密度缩放ctx.scale(dpr, dpr)ctx.beginPath();//此处省略绘制代码ctx.draw();}//canvas渲染尺寸const size = {width: hasLast ? '335rpx' : '361rpx',height: hasLast ? '299rpx' : '330rpx'}//dom标签<canvas id="canvas" style={{...styles.canvas, ...size }} width={canvasWidth} height={canvasHeight} />
以上代码需要用到的公式如下:
渲染比例=设备屏幕宽度/设计稿宽度
canvas渲染尺寸=渲染比例x设计稿元素宽度
canvas画布尺寸=canvas渲染尺寸x设备像素比