canvas移动端画图出现锯齿如何解决(canvas画线去掉锯齿)
前一段时间组员有个项目,需要做大转盘抽奖,找来找去,网上找了个小demo,底层是用canvas
画的,本来我们想在前端实现按中奖比例的随机抽奖行为,测试已经实现了,但是后端开发同事自告奋勇说:不用,我们接口传给你中奖奖品信息。好,????,我就喜欢这么干脆利落,说干就干,转盘功能很快实现了,提测,上线。
到了产品验收环节,亲爱的产品同事揪着一个小问题始终不放,本来不影响主流程,功能已经很哇塞了,但是产品要改,我们只能硬着头皮继续啃代码。
我们遇到的这个问题就是:移动端canvas
画图片时边缘有一圈锯齿,图片也模糊难辨,文字也有这个问题。
ok,问题清楚了,下面开始找解决方案,网上搜了很多,最后总结如下:
出现这个问题的原因应该是手机的宽是720px
的, 而这个canvas
是按照小于720px
画出来的, 所以在720px
的手机上显示时, 这个canvas
的内容其实是经过拉伸的, 所以会出现模糊和锯齿.
解决这个问题,网上主流的有两种方案:
第一种,设置样式解决。
在绘制的过程中画布内容的实际大小是根据 canvas
的 width
与 height
属性设置的,而 style
或者CSS设置的width
与 height
只是简单的对画布进行缩放。
canvas
相当于一个 img
,其中画布的 width
与 height
属性,相当于 img
中图片的原始尺寸;我们使用JS在画布上绘制的内容对应的就是 img
中的图片;而 style
或者CSS设置的 width
与 height
,就是设置 canvas
或者 img
在页面上要显示的大小。
解决模糊的做法,就是将这张“图片”变得高清一点,然后缩小了来显示。
<canvas width="200" height="400" style="width: 100px;height: 200px;"></canvas>复制代码
相当于画了一张200*400
的图片,然后设置他显示成100*200
的大小,这样一来就变得清晰了。
注意:将画布放大之后,绘制的过程中对应的那些坐标,长度等等都要相应的放大。
这种方案多见于2018年以前的文章,2018年以后大都推荐使用另外一种方案。
第二种,使用window.devicePixelRatio
使用window.devicePixelRatio
设备上物理像素和设备独立像素(device-independent pixels (dips))
的比例来设置canvas
实际需要放大的倍数,原理与第一种方法一样,区别在于devicePixelRatio
取出的是实际的比例倍数,在pc端显示为1,移动端各不相同,我在iphone上看是3。
核心代码:
// 真正核心代码 let devicePixelRatio = 1 if (window.devicePixelRatio) { devicePixelRatio = window.devicePixelRatio _this.style.width = width + "px"; _this.style.height = height + "px"; _this.height = height * devicePixelRatio; _this.width = width * devicePixelRatio; } // 下面是应用代码 ctx.lineWidth = 290 * devicePixelRatio; ctx.arc(0, 0, 104 * devicePixelRatio, startAngel, endAngel) // 核心代码 ctx.scale(devicePixelRatio, devicePixelRatio);复制代码
上面代码的核心思路就是,首先获取到设备对应的devicePixelRatio
,这个就是我们在画图,画面,写字的时候的放大倍数,只要是绘画过程中有长度单位,都要放大这个倍数,一个绘画操作完成后,需要调用ctx.scale(devicePixelRatio, devicePixelRatio);
,将画布放大,这时候我们绘画以及画布的实际大小就被放大了,等到渲染的时候,js再根据我们设置在canvas
标签中的宽高样式渲染,实际上就是缩小操作,缩小会让图片变的清晰,这时候图片或者文字都是清晰的。
修改前
修改后
作者:yourbusiness_
链接:https://juejin.cn/post/7031001865479258120