移动视图的事件穿透问题

最近笔者在开发小程序时,遇到一个特别坑的问题。使用 movable-areamovable-view 时,会阻止底层盒子的事件处理(如点击事件、移动事件等)。

movable.png

如图所示,上面是一个movable-area的可移动区域,下面有一个绑定点击事件的底层盒子。现在的情况是可移动盒子是可以在指定范围内移动的,但是点击底层盒子无法触发相应的点击事件。

网上文章提供的一种解决思路说可以通过动态改变可移动区域的大小来解决这个问题,默认设置可移动区域(movable-area)和需要移动的盒子(movable-view)大小一致,需要移动时,设置可移动区域的移动区域,停止移动时,设置为起始值。经过测试,移动后的坐标还是起始坐标,感兴趣的可以尝试下,还是比较坑的。

还有一种解决思路是使用 bindtouchmovebindtouchstartbindtouchend 事件动态计算移动的位置,然后给盒子动态赋值。经过测试,方案的确可行,但是需要大量计算,而且滚动并不流畅,体验很差。难道就没有一种靠谱的解决方案?

经过一系列调研,最终找到了解决方案,那就是使用 pointer-events 属性。

pointer-events 属性

pointer-events CSS 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的 target。-- MDN

pointer-events是一个指针属性,借助它可以实现事件穿透的效果。下面只介绍一下与事件穿透相关的值,其余可以去MDN查看,写的很详细,就不一一赘述了。

1. auto

默认值,与 pointer-events 属性未指定时的表现效果相同。

2. none

元素永远不会成为事件的target。但是,当后台的 pointer-events 属性指定其他的值时,鼠标事件可以指向后台元素,这种情况下,可以在捕获或者冒泡阶段触发父元素的事件侦听器。

解决方案

要想实现事件穿透的效果,只需要为 movable-area 设置 pointer-events: none 属性,同时还需要给 movable-view 设置 pointer-events: auto 属性。这样便可以在移动盒子的同时,也不会影响底层盒子的事件处理。至此,大功告成!!!