JS滑动面板:解决mouseleave事件触发延迟问题
解决Firefox中滑动面板隐藏动画延迟问题
问题原因
Firefox对offsetX/offsetY的计算逻辑与其他浏览器存在差异,当鼠标刚好越过面板边界时,这两个值的计算可能出现偏差,导致你的方向判断条件意外触发return,使得隐藏动画无法立即执行。此外,如果面板存在未完成的动画队列,新的动画会被排队等待,也会造成延迟。
修改方案
- 替换不可靠的
offsetX/offsetY,改用clientX/clientY结合元素的视口位置来判断鼠标离开方向 - 在执行动画前清除所有未完成的动画队列,确保隐藏动画立即启动
- 优化事件绑定的作用域,避免指向错误
修改后的代码
// 优化事件绑定,使用箭头函数确保this指向正确 this.#panel.on("mouseleave", (e) => this.hide(e)); /** * Slides the panel out of viewport. * @param {event object} e */ hide(e) { if (!this.isVisible()) { return; } // 获取面板在视口中的位置信息 const panelRect = this.#panel[0].getBoundingClientRect(); // 判断鼠标是否向面板所在的屏幕边缘方向离开 const isLeavingTowardsEdge = (this.#position === UserInterface.Panel.PositionTop && e.clientY < panelRect.top) || (this.#position === UserInterface.Panel.PositionBottom && e.clientY > panelRect.bottom) || (this.#position === UserInterface.Panel.PositionLeft && e.clientX < panelRect.left) || (this.#position === UserInterface.Panel.PositionRight && e.clientX > panelRect.right); if (isLeavingTowardsEdge) { return; } let margin = this.getMargin(); let css = {}; css[margin.key] = -1 * margin.pixels; // 清除所有未完成的动画,立即执行当前隐藏动画 this.#panel.stop(true).animate(css, this.#speed, () => { this.isVisible(false); }); }
关键说明
getBoundingClientRect()提供的元素位置是基于视口的准确坐标,结合clientX/clientY(鼠标在视口中的坐标),可以更可靠地判断鼠标离开方向,避免Firefox中的计算偏差。stop(true)会清除面板上所有待执行的动画队列,强制立即启动当前的隐藏动画,解决动画排队导致的延迟问题。- 箭头函数替代普通函数绑定事件,避免了作用域丢失问题,确保
this始终指向面板实例。
内容的提问来源于stack exchange,提问作者Samwise_71
相关产品推荐
相关产品推荐

