You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS滑动面板:解决mouseleave事件触发延迟问题

解决Firefox中滑动面板隐藏动画延迟问题

问题原因

Firefox对offsetX/offsetY的计算逻辑与其他浏览器存在差异,当鼠标刚好越过面板边界时,这两个值的计算可能出现偏差,导致你的方向判断条件意外触发return,使得隐藏动画无法立即执行。此外,如果面板存在未完成的动画队列,新的动画会被排队等待,也会造成延迟。

修改方案

  1. 替换不可靠的offsetX/offsetY,改用clientX/clientY结合元素的视口位置来判断鼠标离开方向
  2. 在执行动画前清除所有未完成的动画队列,确保隐藏动画立即启动
  3. 优化事件绑定的作用域,避免指向错误

修改后的代码

// 优化事件绑定,使用箭头函数确保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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:00:22