说图形模块化之前,先回顾下我们之前画的图形.
那是一个多边形,虽然没有闭合,但这不重要。
接下来,咱们就将这个图形封装为一个类对象Poly
Poly对象是对路径的封装,我们可以从两方面来考虑:
图形:路径可以绘制的所有图形,可以是一个图形,也可以是多个图形,只要都在一个路径集合里就行;
样式:路径该有的所有样式了。
接下来我们看一下Poly对象的默认属性:
绘图方法和相关属性
详细解释一下这些属性:
crtPath是建立路径的方法,默认是给了一个绘制多边形的方法,此方法也可以被覆盖。
vertices是多边形的顶点集合。
对于其它图形的相关属性,我没有写,以后需要了可以再去扩展,比如arc的圆心位、半径、起始弧度、结束弧度等等。
绘图方法相关的相关的属性:
○close:否闭合路径
○fill:否以填充方式绘制图形
○strtoke:否以描边方式绘制图形
○shadow:否给图像添加投影
样式相关的属性:fillStyle填充样式、strokeStyle描边样式……这些样式名称和canvas里的样式是一样的,我就不消多说了。
变换相关属性:和canvas里的变换是一样的,分别是位移、旋转、缩放。
Poly的方法:
draw(ctx):绘图方法
checkPointInPath(ctx,{x,y}):检测点位是否在路径中
↓↓↓
注意:
Poly对象中,我对其点位的定义使用了一个Vector2对象。
Vector2是一个二维向量对象,它存储了基本的x、y位置信息,封装了点位的运算方法,比如加、减、乘、除等。
这里我先不对Vector2对象做详细解释,我们先知道它表示一个{x,y}点位即可,后面我们用到了它的哪个功能,再解释哪个功能。
Poly对象建立完成后,咱们就画个三角形试试。
实例化Poly对象:
效果:
为三角形添加划入划出效果:
鼠标选择逻辑:
1.在事件外声明hover变量,存储鼠标划入划出状态。
2.用canvas监听鼠标移动事件,获取鼠标在canvas中的位置
3.使用poly.crtPath(ctx)方法建立路径
4.使用isPointInPath()判断鼠标点位是否在路径中
5.鼠标的选择状态发生了改变,让图形的填充样式也做相应的改变,并绘图。
鼠标划入效果:
把svg多边形画到canvas里
用Poly对象,我们还可以基于svg里的polygon数据绘图并选择。
接下来我用Poly对象画一下那座酷似大象的山。
在svg加载成功后,提取svg里的polygon的顶点,然后将其放到Poly的实例对象的vertices集合里。
parsePoints(mount)解析的就是下面polygon标签的points属性
parsePoints(mount)函数:
页面效果:
进阶:绘制其它图形
重写Poly对象的crtPath()方法,我们还可以绘制除多边形之外的其它图形;
比如用两个三次贝塞尔画一颗爱心:
这里其实还存在了一个问题:
那就是图形通过变换属性发生了位移、旋转或缩放后,使用鼠标相对于canvas画布的点位就无法再对图形做出正确选择。
对于这个问题存在的原因和解决方式,那就是我看修仙小说顿悟出来的绝杀了:
图形选择-物质不易
奥义:图形选择之“物质不易”
现在,咱们来说鼠标如何选择变换后的图形。
首先给大家举个栗子:
在年末世之战的时候,终结者想干掉人类领袖大壮,可是大壮太强,而且其实力需要复杂运算才能知晓。
所以终结者就想回到年,在大壮实力弱小、且已知的情况下将其干掉。
这样根据物质不易法则,年末世之战中的人类领袖大壮也就不会存在。
接下来给大家解密终结者穿梭时间的方法。
终结者需要知道数据:
年大壮的初始属性,比如构成大壮轮廓的顶点集合;
大壮从到的变换信息,比如其大壮移动了多少、旋转了多少、长大了多少。
根据物质不易法则:
物质不变,空间不变;空间不变,时间不变。
将物质不易法则逆推,依旧成立:物质改变,空间改变;空间改变,时间改变。
所以终结者想要回到年,只要根据大壮的变换规则逆向变换自己的位置就可以回到年。
比如:
从年到年,大壮沿x轴移动了,沿y轴移动了,旋转了90度,变大了2倍。
终结者(鼠标点位)就要沿x轴移动了-,沿y轴移动了-,旋转-90度,点位到圆心点的距离缩小2倍。
注意:
终结者的变换顺序要和大壮的变换顺序一致;
终结者改变的只是点位,点没有尺寸,其点位变换本质是在目标对象所在的canvas画布的坐标系的位移。
只有如此,当终结者穿梭到年的时候,才可以精准定位大壮。
图示:
接下来在代码里走一下这个原理:
先画了一颗爱心,其所在的canvas画布坐标系在x、y方向分别位移了(,)
若我的鼠标想要选择这颗爱心,那它的位置就要基于爱心的变换信息反向变换:
x、y方向分别位移(-,-)。
代码如下:
图形变换中的位移说完了,那它的旋转、缩放也是同样道理,就是让鼠标位置基于图形的变换信息反向变换。
下面我直接将所有变换的方法封装到了获取鼠标点位的方法里,即getMousePos(event,poly),event是事件,poly是图形。
代码如下:
mousePos是一个Vector2对象,其中封装了关于向量的常用方法。
如:
好啦,关于变换后的图形选择我们就说到这。
其实图形图形选择的方法是有很多的,下一章我再跟大家说一个图形选择的方法:
图形选择-网格选择
注:物质不易是我从修仙小说上课看的,没有科学依据,只为辅助大家理解代码。