使用setTimeout实现SVG六边形地图tooltip悬停延迟交互的问题咨询
SVG地图Tooltip延迟触发异常修复方案
核心问题根源
- 未声明全局作用域的
hoverTimeout变量,多次触发事件时变量值会被意外覆盖 mouseleave的判断逻辑错误:只有当tooltip还没显示、显示定时器还在计数时才会触发消失逻辑,tooltip完全显示后离开元素不会执行隐藏的延迟定时器- 触发
mouseover时没有清除之前遗留的显示定时器,快速划过多个元素会生成多个待执行的显示定时器,后续到期就会自动弹出tooltip - 定时器执行后没有手动将ID变量置空,导致后续的条件判断失效
修复后完整代码
// Setting the tooltip to appear below the tooltip wrapper gsap.set(tip, { yPercent: 100 }); // 声明两个全局定时器变量,统一管理 let hoverOutTimeout = null; let hoverTimeout = null; // 遍历分组元素绑定事件 for (i = 0; i < lgas.length; i++) { lgas[i].onmouseover = function () { // 先清除所有遗留的定时器,避免之前的任务触发 if (hoverOutTimeout) { clearTimeout(hoverOutTimeout); hoverOutTimeout = null; } if (hoverTimeout) { clearTimeout(hoverTimeout); hoverTimeout = null; } // 新建3秒延迟显示定时器 hoverTimeout = setTimeout(function () { hoverTimeout = null; // 执行后置空,方便后续判断 gsap.to(tip, { yPercent: 0, ease: 'bounce.out' }); }, 3000); } lgas[i].onmouseleave = function () { // 先清除还没执行的显示定时器 if (hoverTimeout) { clearTimeout(hoverTimeout); hoverTimeout = null; } // 不管之前有没有显示,都启动消失延迟定时器 if (hoverOutTimeout) { clearTimeout(hoverOutTimeout); } hoverOutTimeout = setTimeout(() => { hoverOutTimeout = null; gsap.to(tip, { yPercent: 100, ease: 'back.in' }); }, 2000); } }
逻辑说明
- 所有定时器统一管理,每次触发事件先清空所有遗留的定时任务,避免多任务冲突
- 取消了
mouseleave里不必要的判断条件,无论tooltip是否已经完全显示,离开元素都会启动消失延迟 - 每个定时器执行完毕后手动将ID变量置空,保证后续的条件判断逻辑准确
- 快速划过多个元素时,新的
mouseover会直接清掉之前的所有定时器,不会残留待执行的显示任务,也就不会出现tooltip消失后又弹出的问题
内容的提问来源于stack exchange,提问作者Jezza
相关产品推荐
相关产品推荐

