pinter-events,是一个CSS属性,但是它的作用,比起CSS的效果,它更像是做了JS应该做的工作。
可以看一下它在MDN上的简介“CSS属性,指定在什么情况下(如果有)某个特定的图形元素可以成为鼠标事件的target”。这里的图形元素,可以为普通的DOM,也可以为canva和svg等元素。它的属性值见下图。
这里,我们主要关注它的两个属性值,auto,和none,当设置为auto时,和没设置是一样的效果(O.O),当设置为none时,被绑定的元素将不会成为鼠标事件的target,意味着鼠标在这个元素上触发一些事件时会失效,如果被绑定的元素底部有其他的dom元素,则鼠标事件会穿透它,当做它不存在,去触发位于其底部的dom元素的鼠标事件。可能你还是有些模糊,没关系,后面会讲它的有关示例,也就是妙用。它的其它属性值均用于SVG上,感兴趣的可以去查阅相关资料,这里不再赘述。
接下来进入正题,讲它的妙用。当你遇到一个如图所示的缩略图的需求时,你会怎么做?
要求是,当鼠标滑入图片,展示其上的蒙层,蒙层中居中显示“点击查看大图”,当鼠标移开,则蒙层消失。
一般思路有:
·实现思路:img标签初始展示默认图标,当鼠标划入img标签,则展示能盖住img的蒙层,蒙层居中显示提示文字如点击查看大图
·开发过程中的部分代码有:
·实现效果:代码初看可能看不出问题,实际则不然,最终的效果是,蒙层一直在闪烁,可以先想想为什么?
我的猜想是:初始,鼠标滑入img标签,根据代码逻辑,蒙层即展示,蒙层展示后,蒙层成为了鼠标事件的target,隔档了img元素,监听事件即监听到mouseleave事件,则蒙层消失,当蒙层消失后,鼠标又滑入img标签,蒙层又展示,如此循环往复,即出现了蒙层闪烁的效果。那有什么解决方法呢,解决方案很多,这里我简单列出几种。
解决方案一:利用延迟,平缓闪烁的效果。代码如下,鼠标滑入后,蒙层立即展示,当鼠标滑出,监听事件监听到mouseleave,则将控制蒙层消失的逻辑延迟执行,这样的效果比闪烁的蒙层要好很多,当用户快速的滑入点击时几乎看不出差别,但是当鼠标在img上停留时,还是会有一秒一次的闪烁,看起来已经平缓了很多,但是显然跟预期还是有差别的,于是我又想出了第二种解决方案。
解决方案二:增加一个兄弟节点,兄弟节点作为蒙层,监听img标签的滑入,监听其兄弟节点(即蒙层)的滑出。也即,当监听到鼠标滑入img标签时,即插入其一个div作为其兄弟节点,写相对定位的方式让其作为img的蒙层,监听滑出时不再监听img的鼠标滑出,而是转而监听蒙层,这样的效果,与预期的一模一样,代码如下,但是缺点就是需要增加多余的dom,还不够简洁方便,于是就有了解决方案三,也就是这篇文章的主角——pointer-events。
解决方案三:基于原始的代码,在蒙层的样式中加一行代码,即如下所示,即可完美解决这个问题。蒙层将不会再成为鼠标事件的target,意味着任何鼠标事件都能够穿透它,都“看不见它”,这样便能简洁的实现预期的效果图。这是我目前为止,发现最方便的方式,大家有什么更好的解决方法,可以留言交流0.0。
在文章的一开始提到,比起css,它的作用更像是JS,那么,能不能用JS的方式实现类似的效果呢?
在翻阅很多资料后,发现也是可以的,下面的实现基于JQ,来自张鑫旭老师的一篇文章。这里的实现思路是,监听原元素的鼠标事件,然后将其短暂消失,从而获取其dom底部的另一个dom元素,然后组织原元素一系列的鼠标事件的触发,通过事件委托的方式,委托其底部的元素代替其触发鼠标事件,从而做到穿透的效果。
可以看到,这个属性很神奇,其用处也很广泛,像表单项的禁止使用、透明的网页式的海报,还有在做地图项目时,往往需要在地图上方加一些img或者是canvas元素作为提示图标,而这些元素是会影响地图的鼠标事件的触发的,这时pointer-events属性就有很大的作用了,当然,它最广泛的应用,还是SVG。
它这么神奇,那它的兼容性怎么样,见下图,可以看到,它的兼容性也很不错,包括在移动端Android、IOS上的支持都还不错。