我需要知道鼠标光标何时离开div
。所以我联系了mouseout
事件。但是,如果我将鼠标快速移出div
,则mouseout
事件不会触发。这是正确的:鼠标光标 仍然位于div
内,它现在外面 div
,而mouseout
回调没有被称为。 (如果我不快速移动鼠标,它可以正常工作。)
顺便提一下,最新的谷歌浏览器也是如此 - 所以不仅仅是“旧浏览器”问题。
解决方法:
关于这个问题的问题是posed before。显然这只是生活中的事实,我发现的唯一解决方法是手动监控mousemove
事件,每次检查光标的x / y坐标并查看它们是否属于div
的边界框,所以如果光标不在其中,你有更多的机会“注意到”。
与让浏览器本身完成所有这些操作相比,对每个像素移动执行计算都会受到一点性能影响。编码也很繁琐。
关于我的问题......
为什么浏览器无法可靠地捕获mouseout
事件?如果我可以使用上述解决方法可靠地判断鼠标何时离开div
,为什么浏览器不能这样做呢?
我理解(从上面链接的答案)JavaScript不会尝试插入“框架”。假设您在mousemove
上放置document
处理程序,并快速将鼠标移动到完美水平线的右侧200像素,您可能不获得200 {{1}事件。一些将被遗漏。我对此没有任何问题。
但是如果在鼠标越过mousemove
的边界时错过了某些像素移动,为什么还应该跳过div
事件呢?当浏览器最终再次开始注册鼠标位置时(突然快速移动之后),即使鼠标现在在框外里程,关键是它曾经在框中<不再是。那么为什么它不会发射mouseout事件呢?
我只是不明白为什么这对浏览器供应商来说是个难题。 (但我相信可能有一个很好的理由,我觉得这太愚蠢了。)
我发布这个问题主要是出于好奇,但我希望答案可能会提供一些有助于我更有效地解决问题的见解。此外,任何替代解决方案(比上面提到的更快)都是受欢迎的。
答案 0 :(得分:7)
我知道您不需要解决方法,但是您不需要检查鼠标的x / y以了解您是否在元素中。您只需检查触发mousemove事件的元素即可。如果你将鼠标移动到文档上,该事件将从其中一个子项触发,并且您可以将该元素与您的元素进行比较,以了解它是否是其后代之一。
或者你可以上去parentNode树并在你找到你的元素时停止。然后你知道你在元素里面并且仍在其中,否则你到达文档然后你出去了。
有些浏览器实现了mouseenter / mouseleave事件,我注意到这些事件比mouseout更准确。 Prototype和jQuery为没有实现这些新事件的浏览器提供了一种解决方法。 Mouseleave不会从元素的子节点触发,而mouseout则会触发。
答案 1 :(得分:4)
您描述了非常快速地移动鼠标。停止时,指针仍在页面内吗?也就是说,你的鼠标指针是否仍然悬停在可见网页的某些部分上?
如果它已经消失,那么浏览器应该做什么并不一定清楚。 mouseout
事件应该具有relatedTarget
属性,该属性针对鼠标指针所进入的内容。如果鼠标指针已经在页面区域之外,则没有相关的目标指向。
换句话说,当鼠标离开页面区域时,浏览器会停止跟踪它并停止报告其位置。如果你足够快地移动鼠标,从浏览器的角度来看,鼠标就会消失。直到您将鼠标放回可浏览页面的边界框中,浏览器才知道它在哪里,然后触发所有适当的基于移动的操作(如mouseout)。
答案 2 :(得分:1)
为什么浏览器无法可靠地捕获mouseout事件?如果我可以使用上面的解决方法可靠地判断鼠标何时离开div,为什么浏览器不能这样做呢?
我想你在说:
时自己回答了这个问题与让浏览器本身完成所有这些操作相比,对每个像素移动执行计算都会受到一点性能影响。
浏览器不会在帧之间进行插值,因此,正如您所说,它会需要更多的资源和内存,这可能就是它没有“修复”的原因。
如果在鼠标越过div的边界时错过了某些像素移动,为什么还应该跳过mouseout事件呢?当浏览器最终再次开始注册鼠标的位置时(在突然快速移动之后),即使鼠标现在在盒子外面数英里,关键是它曾经在盒子中而不再是。那么为什么它不会随后触发mouseout事件呢?
我不确定,但我不认为这是“它已经存在且现在已经存在”的条件。相反,它是否跨越该边界(如果MouseX - ElemOffsetX= 1
)。我同意,它没有那么多意义,但可能是因为如果你将值设置为> 1
,它会多次触发事件。否则,它必须跟踪不属于JS性质的事件,看它是如何将事件asynch添加到堆栈中。
您可以尝试使用jQuery's mouseleave event。这样做有两件事,它延迟了事件的触发:
答案 3 :(得分:1)
我遇到过这个问题几次,我开始接受这个问题作为生活中的事实。但是根据你的需要,你可以像我一样使用CSS。例如,如果我只想显示/隐藏另一个被悬停的元素的元素库,那么CSS就是可行的方法。这是一个可靠,可靠的例子:
.large {
width: 175px; height: 175px;
position: absolute;
border-radius: 100%;
/*hide the glass by default*/
top: -9999px;
left: -9999px;
opacity: 0;
transition: opacity .2s ease-in-out;
z-index: 100;
pointer-events: none;
}
.small:hover + .large {
opacity: 1;
}
答案 4 :(得分:0)
我发现你的问题和缺乏其他明确的答案很有用,因为它告诉我必须创建一个解决方法。我使用你的问题和其他贡献者提出的想法做了。
当我使用jquery mouseleave elem.bind('mouseleave',data,mouseLeavesZone)时遇到同样的问题;
问题是间歇性的,可能与客户端上繁忙的CPU有关。比如说,当你的鼠标离开div时,CPU正在其他地方忙碌。那么这可能是导致bug的原因似乎是合乎逻辑的。我同意;这应该由浏览器供应商修复。
请参阅http://jsfiddle.net/bgil2012/gWP5x/1/
(旁白:我的JQuery代码需要使用较旧的jQuery方法,因为它必须在运行jQuery 1.4的Drupal 7中运行,此时并且不应用即将发布的补丁)。
答案 5 :(得分:0)
这是一个简单的解决方法。
在您的onMouseOver侦听器中,您可以将“ mousemove”侦听器添加到窗口:
<div onMouseOver={() => {
setMouseOver(true)
let checkMouseLeave = (e: MouseEvent) => {
if (rootRef.current
&& !rootRef.current.contains(e.target as HTMLElement)) {
setMouseOver(false)
window.removeEventListener('mousemove', checkMouseLeave)
}
}
window.addEventListener('mousemove', checkMouseLeave)
}
></div>
然后,您可以检查每次鼠标移动,直到鼠标位于div之外(在本示例中为rootRef.current)。