通过绝对定位元素传递鼠标事件

414

我正在尝试在一个元素上捕获鼠标事件,而该元素上方又有另一个绝对定位的元素。

目前,绝对定位元素上的事件会被它拦截并冒泡到其父级,但我希望它对这些鼠标事件是“透明”的,并将它们转发给它后面的任何元素。 我应该如何实现这一点?

6个回答

661

3
谢谢!这是现代(非IE)浏览器的完美解决方案。在发布这个问题时,我不认为 pointer-events 存在!将来可能会把采纳答案改成这个。 - s4y
2
我刚刚将被接受的答案切换为这个。 pointer-events 的支持仍然不是非常好(http://caniuse.com/#feat=pointer-events),但它正在变得更好。对于更兼容的选项,请选择@JedSchmidt的答案。 - s4y
2
是否有类似于Touch事件的等效项?例如touch-events: none;或类似的内容? - netpoetica
3
除此之外,我需要这个事件对透明元素和它下面的元素都发生。 - RaisinBranCrunch
19
但如果你只想让某些事件(例如滚动事件)穿过顶层元素,但仍希望该元素响应所有其他事件,将pointer-events设置为none会禁用该元素上的所有事件。 - Johann
显示剩余3条评论

69

还有一个需要了解的是...
指针事件可以在父元素(可能是透明的div)中禁用,但仍可启用子元素。 如果您使用多个重叠的div层进行工作,并希望能够单击任何层的子元素,则此功能非常有用。为此,所有父级div都获取 pointer-events: none,并且点击子元素通过 pointer-events: all 重新启用指针事件。

.parent {
    pointer-events:none;        
}
.child {
    pointer-events:all;
}

<div class="some-container">
   <ul class="layer-0 parent">
     <li class="click-me child"></li>
     <li class="click-me child"></li>
   </ul>

   <ul class="layer-1 parent">
     <li class="click-me-also child"></li>
     <li class="click-me-also child"></li>
   </ul>
</div>

12
太棒了!刚刚发现pointer-events:none的妙用,却很快失望地发现它会影响子节点,但是你救了我们一命 :) - Juan Cortés
2
能否简化为 .parent * { pointer-events:all; } 以适用于子元素? - Dmitry
4
应该是 "pointer-events: auto;"。"all" 值仅适用于 SVG。请参阅 https://developer.mozilla.org/zh-CN/docs/Web/CSS/pointer-events。 - Design.Garden
2
@Dmitry 可以确认,这个方法是有效的:.parent { pointer-events:none; }.parent * { pointer-events:auto; } - David

52

如果你只需要鼠标按下事件,你可能可以使用document.elementFromPoint方法,方法如下:

  1. 在鼠标按下时移除顶层元素,
  2. 将事件中的xy坐标传递到document.elementFromPoint方法中,以获取下面的元素,然后
  3. 恢复顶层元素。

9
更多详细解释请参见:http://www.vinylfox.com/forwarding-mouse-events-through-layers/ - Nathan
2
太棒了,我甚至不知道这个方法的存在!它也可以很容易地使用_while_循环来获取光标下的所有元素,然后隐藏顶部元素以查找下一个元素。在此处获取我的版本:https://gist.github.com/Pichan/5498404 - jpeltoniemi
2
这种解决方法的问题在于它无法与页面缩放一起使用。对于移动设备或桌面浏览器缩放的X Y坐标不再有意义,也没有明确的方法来计算缩放。我认为对于捏合缩放来说,这实际上是不可能的。 - Impossibear

10
你没有收到事件的原因是绝对定位元素不是你想要“点击”的元素(蓝色div)的子元素。我能想到最简洁的方法是将绝对定位元素作为要点击的元素的子元素,但我假设你不能这样做,否则你就不会在这里发布这个问题 :)
另一个选择是为绝对元素注册一个点击事件处理程序,并调用蓝色div的点击处理程序,使它们都闪烁。
由于事件通过DOM冒泡的方式,我不确定是否有更简单的答案提供给你,但我非常好奇是否还有其他技巧我不知道!

谢谢你的回复,Loktar。不幸的是,在实际页面中,我不知道绝对定位元素下面有什么,并且可能会有多个可能的目标。我能想到的唯一解决方法是获取鼠标坐标并将其与可能的目标进行比较,以查看它们是否相交。那将是非常糟糕的。 - s4y

4

有一个JavaScript版本可用,它可以手动将事件从一个div重定向到另一个div。

我清理了它,并将其制作成了jQuery插件。

这是Github存储库: https://github.com/BaronVonSmeaton/jquery.forwardevents

不幸的是,我使用它的目的-在Google Maps上覆盖掩码没有捕获点击和拖动事件,并且鼠标光标不会改变,这会降低用户体验,因此我决定在IE和Opera下隐藏掩码-这两个浏览器不支持指针事件。


1
如果您知道需要鼠标事件的元素,并且您的覆盖层是透明的,那么您只需将它们的z-index设置为高于覆盖层即可。在这种情况下,所有浏览器中的所有事件都应该正常工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接