图形模块化2

说图形模块化之前,先回顾下我们之前画的图形.(可回看“图像模块1”)

那是一个多边形,虽然没有闭合,但这不重要。
在这里插入图片描述
这是一个多边形,虽然没有闭合,但这不重要。

接下来,咱们就将这个图形封装为一个类对象 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 画布的点位就无法再对图形做出正确选择。

对于这个问题存在的原因和解决方式,那就是我看修仙小说顿悟出来的绝杀了:

图形选择-物质不易

三、奥义:图形选择之“物质不易”

现在,咱们来说鼠标如何选择变换后的图形。

首先给大家举个栗子:

在2029年末世之战的时候,终结者想干掉人类领袖大壮,可是大壮太强,而且其实力需要复杂运算才能知晓。

所以终结者就想回到1997年,在大壮实力弱小、且已知的情况下将其干掉。

这样根据物质不易法则,2029年末世之战中的人类领袖大壮也就不会存在。

接下来给大家解密终结者穿梭时间的方法。

终结者需要知道数据:

1997年大壮的初始属性,比如构成大壮轮廓的顶点集合;

大壮从1997到2029的变换信息,比如其大壮移动了多少、旋转了多少、长大了多少。

根据物质不易法则:

物质不变,空间不变;空间不变,时间不变。

将物质不易法则逆推,依旧成立:物质改变,空间改变;空间改变,时间改变。

所以终结者想要回到1997 年,只要根据大壮的变换规则逆向变换自己的位置就可以回到1997年。

比如:

从1997年到2029年,大壮沿x 轴移动了100,沿y 轴移动了200,旋转了90度,变大了2倍。

终结者(鼠标点位)就要沿x 轴移动了-100,沿y 轴移动了-200,旋转-90度,点位到圆心点的距离缩小2倍。

注意:

终结者的变换顺序要和大壮的变换顺序一致;

终结者改变的只是点位,点没有尺寸,其点位变换本质是在目标对象所在的canvas画布的坐标系的位移。

只有如此,当终结者穿梭到1997年的时候,才可以精准定位大壮。

图示:
在这里插入图片描述

接下来在代码里走一下这个原理:

先画了一颗爱心,其所在的canvas 画布坐标系在x、y方向分别位移了(300,400)
在这里插入图片描述
在这里插入图片描述

若我的鼠标想要选择这颗爱心,那它的位置就要基于爱心的变换信息反向变换:

x、y方向分别位移(-300,-400)。

代码如下:
在这里插入图片描述

图形变换中的位移说完了,那它的旋转、缩放也是同样道理,就是让鼠标位置基于图形的变换信息反向变换。

下面我直接将所有变换的方法封装到了获取鼠标点位的方法里,即getMousePos(event,poly) ,event是事件,poly 是图形。

代码如下:
在这里插入图片描述

mousePos 是一个Vector2 对象,其中封装了关于向量的常用方法。

如:
在这里插入图片描述

好啦,关于变换后的图形选择我们就说到这。

其实图形图形选择的方法是有很多的,下一章我再跟大家说一个图形选择的方法:

图形选择-网格选择

注:物质不易是我从修仙小说上课看的,没有科学依据,只为辅助大家理解代码。


摘至开课吧前端团队,阅读后颇有收获分享至此,希望对大家有所帮助~