考虑一个简单的元素及其相关的CSS:
Hover me !
#content {
width: 100px;
height: 100px;
}
#content:hover {
transform: translateY(500px);
transition: transform 1s 500ms;
}
JSFiddle
原则是直截了当的:当元素悬停时,它必须下降.问题是,当鼠标不移动时,:hover
即使元素不再在物理上低于鼠标(由于翻译),状态也会保持不变.只有在鼠标移动后才会更新状态.
注意光标(指针)及其与元素的相对位置!
当一个JavaScript函数必须仅在鼠标位于元素上时执行时,这是一个真正的问题timeout
:
// The mouseleave event will not be called during the transition,
// unless the mouse move !
element.on('mouseenter', executeAfterTimeout);
element.on('mouseleave', cancelTimeout);
所以这是我的问题:
这种行为是否正常(符合规范)?
有哪些解决方案可以避免这个问题?
编辑:为了给你一个上下文,这是我想要具体做的事情:使用JavaScript,当鼠标在元素上时显示工具提示(并在鼠标离开时隐藏它).但是transform
当用户点击它时,可以使用相同的元素.如果用户只是在不移动鼠标的情况下单击,则工具提示将保持显示,这是一个真正的问题.如何检测元素消失?
原则是直截了当的:当元素悬停时,它必须下降.问题是,当鼠标不移动时,即使元素不再在物理上低于鼠标(由于转换),也会保持:悬停状态.只有在鼠标移动后才会更新状态.
所以这是我的问题:
这种行为是否正常(符合规范)?
是.这种行为很正常.虽然标准中没有逐字说明,但在此详细说明:http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
把这个小提琴作为参考:http://jsfiddle.net/Blackhole/h7tb9/3/
上面div
有直接绑定它的鼠标事件.较低的div
鼠标事件绑定到其父级.拿起下面一个.在一个边缘缓慢移动鼠标并观察控制台以查看会发生什么.
你触摸边缘,mouseover
并mouseenter
快速连续地(悬停)被解雇.
结果,内在div
翻译.
没做什么.没有事件被触发,所以没有任何反应.
将鼠标移到外部div
.mousemove
火灾和内在div
仍然翻译.
慢慢移开鼠标.mouseout
并且mouseleave
快速连续发射,内部div
转换回原来的位置.
这里描述了:http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-mouseevents下的鼠标事件顺序部分.
上面的步骤3很重要.因为你什么都不做,所以没有事件发生,因此没有任何反应.如果内部div
在此步骤中反弹回其原始位置,则意味着在没有任何事件的情况下发生了激活!
这与事件的定义一致,如本节中的文档:http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#glossary-event说:
事件是与其事件目标相关联的某些事件的表示(例如,鼠标单击元素的表示,从元素中删除子节点,或任何数量的其他可能性).每个事件都是一个特定事件类型的实例化.
现在看一下这里的文档:http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#event-flow,就在3.2节开始之前,它说:
事件完成其传播路径的所有阶段后,其Event.currentTarget必须设置为null,并且Event.eventPhase必须设置为0(NONE).Event的所有其他属性(或从Event派生的接口)都保持不变(包括Event.target属性,该属性必须继续引用事件目标).
最后一行(括号中)很重要.即使事件完成,event.target仍继续引用事件目标.
现在选择div
小提琴中的鞋面作为参考.在mouseenter
它div
自己被翻译.它是否远离鼠标指针下方无关紧要.event.target仍然引用它,如果没有其他鼠标事件发生,则没有任何反应,它仍然被翻译.那一刻您移动鼠标(任何地方或缩小),激活发生在event.target(这仍然是这个div
)和现在的用户代理发现鼠标指针不再是在元素并立即mouseout
和mouseleave
事件触发(在射击之后mousemove
)导致div
翻译回来.
2.避免这个问题的解决方案是什么?
编辑:为了给你一个上下文,这是我想要具体做的事情:使用JavaScript,当鼠标在元素上时显示工具提示(并在鼠标离开时隐藏它).但是当用户点击它时,可以转换相同的元素.如果用户只是在不移动鼠标的情况下单击,则工具提示将保持显示,这是一个真正的问题.如何检测元素消失?
如果你看看div
这个小提琴下面的实现:http://jsfiddle.net/abhitalks/h7tb9/2/ ; 与上部div相比,当鼠标移动时没有颤动/抖动.这是因为div
事件是在父母身上处理的,而不是自身.
因此,这可能是您的用例的一个解决方案.
看这个演示:http://jsfiddle.net/Blackhole/nR8t9/9/
这解决了您的编辑问题 显示工具提示mouseover
.工具提示隐藏起来mouseleave
.你可以转换相同的元素click
.如果您只是click
不移动鼠标,工具提示就会隐藏.
在这里,如果您click
正在翻译该元素,则不会再进行任何hover
操作.工具提示本身使用:before
伪元素实现.这会将工具提示和您想要更改的元素分开click
.您仍然可以处理元素本身的事件.不需要超时,因为它由css本身处理.如果你mouseout
,工具提示会在延迟后隐藏.
希望有所帮助.