图形模块化1

图形选择,是可视化交互中必然会遇到的,它在可视化方面的面试中出现概率是最高的。

我在这里会从两个方向来说,分别是svg和canvas。

至于普通DOM 的选择,我就不消多说了。

因为svg 的选择是最简单的,所以咱们先说svg。

一、图形选择-svg

svg 的选择方式和普通DOM 的选择方式是一样的。

比如画一个三角形,然后为其正常添加鼠标划入划出事件:
在这里插入图片描述
在这里插入图片描述在实际的工作中,我们可能会对复杂图形做出交互选择。

就比如图片里有一座酷似大象的山,我们把鼠标划到山上的时候,要做出一些相应的提示。
在这里插入图片描述
这个时候,我们可以用Illustrator 来绘制山体轮廓。
在这里插入图片描述
在绘制完成后,ctrl+shift+S 另存为svg 文件即可。

在另存为的时候,还会弹出svg 配置窗口:
在这里插入图片描述
在上面的窗口里面,我们可以点击“SVG 代码”按钮,查看相应的SVG代码:
在这里插入图片描述
从SVG代码中可以看出,图层的名称就是SVG 元素的id。

有了SVG 文件之后,我们就需要将其导入HTML 页面里。

因为这个文件是用Adobe 的Illustrator 软件生成的,所咱们就用Adobe 官方推荐的方式导入svg 文件:
在这里插入图片描述

二、svg绘图面对的两种问题

使用 标签的src 属性引入了svg 文件后,我们就需要为svg 中的元素添加鼠标事件了,这个过程需要考虑两个问题:

  1. svg 文件的引入是个异步事件,我们需要将在svg 文件引入成功后在获取svg 中的元素。
  2. svg 中的元素中的元素无法直接用当前页面的document 获取,svg 文件有自己的document 对象。

第1个问题:
可用为window 或embed 添加onload 事件来解决,如:
在这里插入图片描述
第2个问题:
要先用embed.getSVGDocument() 方法获取svg 自己的document 对象,然后再使用此document对象获取SVG 中的元素。

完整代码:
在这里插入图片描述
页面效果:
在这里插入图片描述
svg 绘图时,如果图形数量非常大,其渲染速度就会非常慢,而且它还不适合做图像处理。

这时,就需要选择canvas 了。

既然选择canvas,那我们就必须考虑如何选择canvas 中的图形了。

接下来,我具体给大家说多边形网格方法:

canvas 内置的isPointInPath(x,y) 方法。

多边形网格化方法。

三、图形选择-isPointInPath(x,y)

isPointInPath(x,y) 是canvas 2d中的内置方法,它可以判断一个点位是否在路径中。

isPointInPath(x,y) 面向的对象是路径,所以对文字、fillRect()、strokeRect()不好使。

首先,咱们先回顾一下路径的基本概念:

在我们使用canvas 的getContext(‘2d’) 方法获取canvas 上下文对象ctx 的时候, ctx上便挂载了一个空的路径集合。

在ctx.beginPath() 之后,所绘制的所有路径都会被添加到这个路径集合里。

isPointInPath(x,y) 方法判断的就是x、y 点是否在这个路径集合的所有路径里。

这个路径可以不用画出来,只要路径集合里有路径即可。

注意,在下一次ctx.beginPath() 时,路径集合会被置空。

接下来我们看一下isPointInPath 的使用方法。

我用三个点画了一条折线,没有将其闭合:
在这里插入图片描述
在这里插入图片描述ctx.isPointInPath(250,100) 返回了true,就是点(250,100) 在刚才的3个点围成的闭合路径之中。

简单总结一下:

  1. 网路径集合中绘制了一条由3 个点组成的折线,未将其闭合(是否闭合无所谓)。
  2. 检测点(250,100) 是在上面的3 个点围成的图形中的,所以ctx.isPointInPath(250,100) 为true。
  3. ctx.isPointInPath(250,100) 方法是在绘图之前执行的,这说明isPointInPath(x,y)方法的使用并不需要把路径实际画出来。

这时候,大家可能会想:

如果我把鼠标点作为检测点,鼠标每次移动都要判断其是否在图形中,是不是每次鼠标移动都要把路径再画一遍?

这个答案要视情况而定:

路径集合没有被清空,那鼠标移动时都可以正常检测:
在这里插入图片描述
可是当我在画完路径后再画点东西时,用beginPath()方法把以前的路径给清空了;

画出了一个圆,那我们就无法再对以前的路径进行isPointInPath() 判断了。

例如:
在这里插入图片描述
在这里插入图片描述
这就是后一种情况:

路径集合被清空时,可以把绘制路径的步骤封装到一个方法里;

在鼠标移动时,执行此方法,把路径集合先清空,再放入我们需要检测的路径:
在这里插入图片描述
到这里,我们就可以做一些简单的图形选择的项目了。

但是在面对大一点的项目是,还是建议大家用模块的思想将上面功能模块化。


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