最近做了一个画图的功能,后端提供棋盘数据,前端需要把数据转换成一个棋盘画出来,当时有两种实现方法,一种是使用canvas画图,一个是使用svg画图.
ui提供的设计稿如下:
由于这是一个轮播图,当后端返回多少张棋盘数据时,就需要渲染多少张棋盘,最多有十张,基于canvas和svg画图,为了保证页面的首次渲染时长最优,就是不使用库来画,正好可以熟悉一下canvas和svg的基础.
由于是在移动端的页面,所以首选就是使用rem单位,但是画着画着就出现了问题
svg画简单形状的代码是
使用rem单位画线
使用rem单位画圆
效果如下:
在电脑上能够正常显示,但是到iphone13上,就显示不出来了.
我发现是小于1的rem单位的显示不出来,不过我没有使用各种各样的机型测试,但是iphone13就不行,那就只能放弃了.
所以就只能依赖js计算
40px的线条距离:40 * document.documentElement.clientWidth / 375;
虽然不能使用rem单位,但是可以使用百分比,使用svg的DOM元素使用rem单位还是没有问题的,使用百分比就能够正常显示
使用百分比单位画线
使用百分比单位画圆
不过使用js计算一次就可以了,百分比对着ui稿我还得计算一遍,所以我就直接使用document.documentElement.clientWidth计算了.
很快棋盘的样式就画好了
所以很快就被ui设计师打了回来,没有光泽,她说棋子需要画渐变,也需要有阴影,不然不好看.
加渐变(first:没渐变,second:有渐变)
效果对比如下:
渐变兼容性在PC,iphone,ipad,安卓都支持~
加阴影(first:没阴影,second:有阴影)
效果如下:
阴影没有加渐变这么顺利,出现了新的问题
排查原因:发现去掉去掉filter标签就能够看到棋子.
于是我查看svg中filter标签的兼容性。如下:
https://caniuse.com/?search=filter svg
上面写着IOS6就开始支持了,但是在iphone13中就是没有显示出来,所以就只能不能这样画阴影了,得另寻他路.
重叠元素加阴影(first:没阴影,second:有阴影)
效果如下:
不过这个需要特别注意顺序,阴影需要在下面显示,所以要先绘制阴影,不然就会把棋子盖住,效果像下面这样:
突然发现使用重叠元素加出来的阴影更加好看.
svg中的cricle标签没有z-index层级之说
解决办法:svg面积增大,svg中的元素x,y轴偏移,根据rect画圆角矩形
画圆角矩形
// x,y是矩形的起点;w,h是矩形的宽高;r是圆角矩形的半径
效果如下:
从上面效果来说,我觉得svg画的棋盘在移动端更高清,而canvas更像是一张图片,对效果有更加浓厚的兴趣的可以去下载一下源码,然后自己手动在手机上看看效果.
我只是通过谷歌浏览器的lighthouse测量了一下,下面是绘制十张棋盘的测试结果,当然觉得这样测量不准确的,也欢迎下载源码自己去测试一下~
从上面结果上看,svg和canvas画十张棋盘的性能,svg优胜一点点,总阻塞时间svg快了100ms的样子.
为了保证公平性,源码中没有使用任何库,只是js操作,十张棋盘的数据也是一样的.
gitee地址:svg_vs_canvas_chess: svg和canvas在移动端适配比较 (gitee.com)
github地址:https://github.com/tiantianhy/svg_vs_canvas_chess
上述分享中,如有疑问和想法,欢迎一起探讨~