如何在JavaScript的wheel事件中限制GSAP动画仅触发一次?
解决滚动触发GSAP动画多次的问题
方案1:完善状态锁+冷却时间
你的现有代码用了isAnimating状态锁,但触摸板长滚动时wheel事件会连续高频触发,可能在状态锁更新前就多次进入判断。可以给状态锁加上冷却时间,确保动画结束后或一段时间内不再响应滚动触发:
let isAnimating = false; const COOLDOWN_TIME = 1000; // 冷却时间,可根据动画实际时长调整 window.addEventListener('wheel', (event) => { if (!isAnimating) { isAnimating = true; // 播放GSAP动画 slideTimelines[0].play(0).then(() => { // 动画结束后延迟解锁,避免短时间内重复触发 setTimeout(() => { isAnimating = false; }, COOLDOWN_TIME); }); } });
方案2:使用防抖函数
防抖函数可以让连续触发的高频事件只执行一次,完美适配这类滚动触发场景:
let isAnimating = false; // 防抖函数:连续触发时只执行最后一次 function debounce(func, delay = 500) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); }; } const handleWheel = debounce(() => { if (!isAnimating) { isAnimating = true; slideTimelines[0].play(0).then(() => { isAnimating = false; }); } }); window.addEventListener('wheel', handleWheel);
方案3:结合滚动方向判断(可选)
如果只需要在特定滚动方向(比如向下)触发动画,可以加上方向判断,进一步减少误触发:
let isAnimating = false; const COOLDOWN_TIME = 1000; window.addEventListener('wheel', (event) => { // 仅响应向下滚动(deltaY>0),可根据需求改为向上(deltaY<0) if (!isAnimating && event.deltaY > 0) { isAnimating = true; slideTimelines[0].play(0).then(() => { setTimeout(() => { isAnimating = false; }, COOLDOWN_TIME); }); } });
关键说明
isAnimating状态锁必须绑定到GSAP动画的完成回调(.then()),确保动画完全结束后才解锁。- 冷却时间或防抖延迟建议设置为略短于动画时长,既保证只触发一次,又不会让用户等待太久。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

