这篇文章写得有点晚了.原因?因为我写着写着就忘了有这一茬还没写….
canvas的isPointInPath是一个非常重要的函数,其作用是判断某一点是否是在某个路径内.其语法如下:
context.isPointInPath(x,y)
其中很明显,x和y就是一个点的坐标了.
canvas有个致命的缺点就是本身缺乏交互性,比如这个问题:
问题1:我画了一个黑圆,想让鼠标经过的时候颜色变红,鼠标移出后又变回来
–很简单的功能吧,用CSS都可以轻松做到,但在canvas中,就是个难事了.
基本用法
这时候isPointInPath就派上了用场.他的用法是,先画出一条路径,然后调用isPointInPath,此时isPointInPath就能判断你传入的这个点是否在这个路径之内.
isPointInPath虽然判断出了点在路径中,但是呢,我们要把原来的黑色变红,就得重绘一下canvas.
然后还有个问题,当鼠标进入形状区域又出来之后,我们又要把红色变成黑色,又得重绘一下canvas–看起来很麻烦是不?
所以代码如下:
HTML代码:
大家注意我的css里给canvas外面的DIV加了个相对定位,额外提醒一下,这个非常重要,下面我们获取鼠标坐标的时候必须要依靠这个.
JS代码:
这样一来我们的目的达到了.鼠标一进一出,再一进一出,再一进一出….也不会出错.
但要是细看一下代码,会发现实现这个效果我们付出了太多,首先是给canvas加上了onmousemove事件,这个事件在鼠标移动的时候会一直触发,很浪费资源;然后,鼠标每一次移动,都会执行draw函数,画图形,区别只有填充是黑色还是红色,也就是说我们重绘了太多次.我们投入这么多资源,只实现了如此简单的效果,实在是不甘心.
当然,函数是可以优化的,重绘次数可以减少到进来一次出去一次,但用canvas实现交互的流程就是这样
得到鼠标坐标–判断图形–清空区域–以相同位置不同颜色重绘图形
以后的文章我会讲一些canvas的高级技巧,比如怎么尽可能的不重绘.现在先看下面的问题.
进阶用法
问题2:如果canvas上有10条路径,那怎么判断坐标是在哪一条路径中呢?
答案就是那个最笨的答案:每结束一条路径时,都必须进行判断,此时得出的结果就是针对你当前的这个路径而不是其他路径.
isPointInPath只对当前路径有效!
也就是说你不能画了10条路径后突然跑去判断点是不是在第1条路径之中.
为什么要这样呢?因为canvas中路径是不能保存的,不能像一个变量那样保留起来供后面再用.这样一来你想要重现这个路径的话,惟一的办法就是:按照之前的值,之前的函数,重新画一遍.
所以我把上面的代码改一下,画出两个黑色的图形,然后都实现hover变色的效果.
虽然只增加了一个图形,但代码却大变样.先是把两个画图形的函数变成了只画路径,因为我们要判断下isPointInPath再决定用什么颜色填充;
然后用一个数组把函数都保留起来,以便循环调用;
然后像前面说的,每画出一条路径,就判断一下isPointInPath,看看当前是不是在图形中.
查看完整示例页
现在就可以很明显地看到每次mousemove都要清空canvas并重绘,这让我觉得很不爽,要是有100个图形,我相信判断起来效率好不到哪里去.
如上所述,10个图形的实现和2个的就差别不大了,大家自行实验吧.
效率问题以后再说