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

Pass mouse events through absolutely-positioned element

提问人:s4y 提问时间:6/18/2009 最后编辑:Brian Tompsett - 汤莱恩s4y 更新时间:5/18/2021 访问量:164592

问:

我正在尝试捕获一个元素上的鼠标事件,并在其顶部有另一个绝对定位的元素。

现在,绝对定位元素上的事件会击中它并冒泡到它的父元素,但我希望它对这些鼠标事件是“透明的”,并将它们转发到它后面的任何内容。我应该如何实现?

javascript html 事件 dom-events

评论


答:

10赞 Loktar 6/18/2009 #1

您没有收到事件的原因是,绝对定位的元素不是您要“单击”的元素的子元素(蓝色 div)。我能想到的最干净的方法是将绝对元素作为您想要单击的元素的子元素,但我假设您不能这样做,否则您不会在这里发布此问题:)

另一种选择是为绝对元素注册一个 click 事件处理程序,并为蓝色 div 调用 click 处理程序,使它们都闪烁。

由于事件通过 DOM 冒泡的方式,我不确定是否有更简单的答案,但我很好奇是否有其他人有任何我不知道的技巧!

评论

0赞 s4y 6/18/2009
感谢您的回复,Loktar。不幸的是,在实际页面上,我不会知道绝对定位元素下面是什么,并且可能有多个可能的目标。我能想到的唯一解决方法是抓取鼠标坐标并将它们与可能的目标进行比较,看看它们是否相交。那简直太讨厌了。
52赞 Jed Schmidt 6/18/2009 #2

如果您只需要按下鼠标,您可以通过以下方式使用 document.elementFromPoint 方法:

  1. 删除 mousedown 上的顶层,
  2. 将事件中的 and 坐标传递给方法以获取下面的元素,然后xydocument.elementFromPoint
  3. 恢复顶层。

评论

9赞 Nathan 3/24/2012
更多冗长的解释在这里: vinylfox.com/forwarding-mouse-events-through-layers
2赞 jpeltoniemi 5/2/2013
太棒了,我什至不知道这种方法的存在!它也可以很容易地用于使用 while 循环获取光标下的所有元素,以获取最上面的元素,然后隐藏它以查找下一个元素。在这里获取我的版本: gist.github.com/Pichan/5498404
2赞 Impossibear 9/17/2014
此解决方法的问题在于它不适用于缩放页面。对于移动设备或桌面浏览器,放大 X Y 坐标不再有任何意义,也没有明确的方法来计算缩放。我相信对于捏合缩放来说,这实际上是不可能的。
662赞 JanD 6/22/2011 #3
pointer-events: none;

是一个 CSS 属性,它使事件“传递”应用该属性的 HTML 元素。它使事件发生在“下面”的元素上。

详情请见:https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events

几乎所有浏览器都支持它,包括 IE11;05/'21 的全球支持率为 ~98.2%)http://caniuse.com/#feat=pointer-events(感谢 @s4y 在评论中提供链接)。

评论

3赞 s4y 6/23/2011
谢谢!这是现代(和非IE)浏览器的完美解决方案。在发布这个问题时,我认为不存在!我可能会在某个时候将接受的答案切换到这个答案。pointer-events
2赞 s4y 12/18/2012
我只是把接受的答案换成了这个。对 still 的支持不是超级棒,但它正在变得更好。如需更兼容的选项,请使用 @JedSchmidt 的答案。pointer-events
2赞 netpoetica 10/15/2014
触摸事件是否有等效项?touch-events:无;或者类似的东西?
3赞 RaisinBranCrunch 4/15/2017
除了我需要对透明元素及其下方的元素都发生此事件。
20赞 Johann 7/31/2017
但是,如果您只想让某些事件(如滚动事件)通过,但顶部元素仍要响应所有其他事件,该怎么办?将 pointer-events 设置为 none 会终止 top 元素上的所有事件。
1赞 ricosrealm 2/26/2012 #4

如果您知道需要鼠标事件的元素,并且您的叠加层是透明的,则可以将它们的 z 索引设置为高于叠加层的元素。当然,在这种情况下,所有事件都应该在所有浏览器上工作。

4赞 Mikepote 3/28/2013 #5

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

我清理了它,把它变成了一个jQuery插件。

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

不幸的是,我使用它的目的 - 在 Google 地图上覆盖蒙版没有捕获点击和拖动事件,并且鼠标光标没有改变,这降低了用户体验,以至于我决定将蒙版隐藏在 IE 和 Opera 下 - 这两个浏览器不支持指针事件。

69赞 Allisone 11/7/2014 #6

也很高兴知道...
可以为父元素(可能是透明的 div)禁用指针事件,但为子元素启用指针事件。 如果您使用多个重叠的 div 图层,并且您希望能够单击任何图层的子元素,这将非常有用。为此,所有育儿 div get 和 click-children get 指针事件都由
pointer-events: nonepointer-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赞 Juan Cortés 7/20/2015
太棒了,在发现的高潮和儿童节点受到影响的迫在眉睫之后,您节省了这一天:)pointer-events:none
2赞 Dmitry 3/16/2018
可以归结为:为了孩子吗?.parent * { pointer-events:all; }
4赞 Design.Garden 12/19/2019
它应该是 “pointer-events: auto;”。“all”值仅适用于 SVG。查看 developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
2赞 David 2/8/2022
@Dmitry 可以确认,这确实有效:并且.parent { pointer-events:none; }.parent * { pointer-events:auto; }