前言
通常来说,大家对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 在线演示,使用鼠标滚轮缩放图形。