You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

JavaScript中如何在特定条件下停用已激活的mouseover/mouseout事件监听器?

如何在特定条件下启用/停用SVG元素的mouseover/mouseout事件

你的问题核心在于:匿名事件监听器无法被移除,而且每次调用makeHover()都会给元素添加新的监听器,所以即使currentColor变成1,之前的监听器依然在生效。下面给你两种可行的解决方案:

方案一:抽离命名事件函数,动态添加/移除监听器

这种方法的关键是把原本写在addEventListener里的匿名函数抽成独立的命名函数,这样后续可以用removeEventListener精准移除它们。

  1. 先定义独立的事件处理函数:
// 抽离mouseover处理逻辑
function handleMouseOver(event) {
  event.target.style.fill = "rgb(168,168,168)";
  event.target.style.pointerEvents = "all";
  event.target.style.cursor = "pointer";
  event.target.style.strokeOpacity = "1";
  event.target.style.fillOpacity = "0.3";
  event.target.style.transitionDuration = "0.5s";
  event.target.style.transitionTimingFunction = "ease-in";
}

// 抽离mouseout处理逻辑
function handleMouseOut(event) {
  event.target.style.fill = "none";
  event.target.style.stroke = "white";
  event.target.style.pointerEvents = "all";
  event.target.style.strokeOpacity = "1";
  event.target.style.fillOpacity = "0.1";
  event.target.style.transitionDuration = "0.5s";
  event.target.style.transitionTimingFunction = "ease-out";
}
  1. 写一个切换事件状态的函数,根据currentColor的值决定添加或移除监听器:
let currentColor = 0;

function toggleHoverEffects() {
  svgAll.forEach(item => {
    if (currentColor === 0) {
      // 启用hover效果:添加监听器
      item.addEventListener('mouseover', handleMouseOver);
      item.addEventListener('mouseout', handleMouseOut);
    } else {
      // 停用hover效果:移除监听器
      item.removeEventListener('mouseover', handleMouseOver);
      item.removeEventListener('mouseout', handleMouseOut);
      // 可选:移除后恢复元素初始样式,避免停留在hover状态
      item.style.fill = "none";
      item.style.stroke = "white";
      item.style.strokeOpacity = "1";
      item.style.fillOpacity = "0.1";
    }
  });
}
  1. 使用方式:
  • 当你需要启用hover效果时,设置currentColor = 0,然后调用toggleHoverEffects()
  • 当需要停用效果时,设置currentColor = 1,再调用toggleHoverEffects()

方案二:在事件处理函数内部判断条件

如果你的状态切换比较频繁,不想反复添加/移除监听器,可以直接在事件触发时判断currentColor的值,只有满足条件才执行样式修改:

let currentColor = 0;

function handleMouseOver(event) {
  // 不满足条件直接退出,不执行任何操作
  if (currentColor !== 0) return;
  
  event.target.style.fill = "rgb(168,168,168)";
  event.target.style.pointerEvents = "all";
  event.target.style.cursor = "pointer";
  event.target.style.strokeOpacity = "1";
  event.target.style.fillOpacity = "0.3";
  event.target.style.transitionDuration = "0.5s";
  event.target.style.transitionTimingFunction = "ease-in";
}

function handleMouseOut(event) {
  if (currentColor !== 0) return;
  
  event.target.style.fill = "none";
  event.target.style.stroke = "white";
  event.target.style.pointerEvents = "all";
  event.target.style.strokeOpacity = "1";
  event.target.style.fillOpacity = "0.1";
  event.target.style.transitionDuration = "0.5s";
  event.target.style.transitionTimingFunction = "ease-out";
}

// 只需要初始化添加一次监听器
svgAll.forEach(item => {
  item.addEventListener('mouseover', handleMouseOver);
  item.addEventListener('mouseout', handleMouseOut);
});

这种方法的好处是只需要添加一次监听器,后续只需要修改currentColor的值,事件触发时会自动判断是否执行逻辑。

为什么你的原代码失效?

你原代码中每次调用makeHover()都会给每个SVG元素新增匿名的mouseover/mouseout监听器,这些匿名函数没有唯一的引用标识,所以即使currentColor变成1,之前添加的监听器依然存在并会被触发。而且你无法用removeEventListener移除它们,因为找不到对应的函数引用。

内容的提问来源于stack exchange,提问作者Julian Roma

火山引擎 最新活动