前言
通常来说,大家对svg
与canvas
的首要区别与印象,是svg
具有与设备、分辨率无关的特性,转而普遍就认为canvas
区别于svg
的一大劣势就在于此。
个人愚见,更合理的描述应该是canvas
对设备与分辨率“敏感”。
canvas的高清屏适配
svg
自适应适配了Retina
高清屏的,而如果你不做任何处理,初始化一个canvas
,在具有缩放设置的屏幕上显示出来的内容看起来是糊的:
初见之下,很难不让人苦恼。
其实解决这个问题的办法及其简单,首先需要获取一个值:let dpr = window.devicePixelRatio;
。
在普通屏幕下,dpr
为1
,而高清屏或者人为调整过系统缩放设置的屏幕下,dpr
大于1
,多数时候大致为2
或者3
。
所以,解决办法就是将canvas
的真实宽高canvas.width/height
乘以dpr
,将canvas.style.width/height
设置为正常宽高。
比如目标canvas
的宽高为200
,那么canvas.style.width/height
设置为200px
,而canvas.width/height
设置为400
即可。
如图所示:
这样子,提供足量多的“真实”像素,canvas
自然就不糊了。
无损缩放
再说到canvas
实现类似svg
的无损缩放。
最简单的无损缩放,比如放大2
倍,使用绘图上下文context.scale(2, 2);
再绘制图形即可。
而通常缩放由事件来触发,这个技巧常用于大数据量的展示和交互,事件有一个坐标x, y
,表示用户关注点的位置,图形也应以此坐标点来进行缩放,而不同的缩放点也会使得缩放结果不同,如图:
连接圆心O
和缩放事件发生点E
,使用中学学过的向量的知识,很容易就可得到:
表示得更清楚一点即:
至此,目标位置就确定好了,同样的,配合使用context.scale(zooming, zooming);
也就完成了canvas
中无损缩放的整个过程。
CodePen 在线演示,使用鼠标滚轮缩放图形。