如何解决不同DOM按钮触发GSAP动画reverse()反向播放的作用域问题
问题原因
- 你每次点击汉堡按钮都会重复往时间线
tb里追加新的fromTo动画,时间线的内容会越叠越多,反向播放的逻辑自然会错乱 - 关闭时你直接同步移除
_active类,会导致反向动画还没播放完菜单就被隐藏,看不到消失效果 - 没有做状态拦截,重复点击汉堡/关闭按钮会触发多次无效动画
修复后的完整代码
const burger = document.querySelector('.burger'); const menu = document.querySelector('.menu'); const menuClose = document.querySelector('.close'); // 提前初始化完整时间线,设置paused: true 默认不自动播放 const tb = gsap.timeline({ defaults: {duration: .3}, paused: true, // 反向动画播放完成后再移除active类,保证动画可见 onReverseComplete: () => { menu.classList.remove('_active'); } }); // 提前把所有动画片段加入时间线,不要在点击事件中动态追加 tb.fromTo(".menu", { opacity: 0}, { opacity: 1}) .fromTo(".menu__nav", { opacity: 0}, { opacity: 1}) .fromTo(".social", { opacity: 0}, { opacity: 1}) .fromTo(".menu__right", { opacity: 0}, { opacity: 1}); burger.addEventListener('click', () => { // 拦截动画播放中、菜单已打开状态的重复点击 if (tb.isActive() || menu.classList.contains('_active')) return menu.classList.add('_active'); // 从时间线起始位置开始正向播放入场动画 tb.play(0); }); menuClose.addEventListener('click', () => { // 拦截动画播放中、菜单已关闭状态的重复点击 if (tb.isActive() || !menu.classList.contains('_active')) return tb.reverse(); });
核心改动说明
- 把所有动画片段提前初始化到时间线里,避免点击事件中动态追加导致的时间线内容重复堆叠
- 给时间线加
paused: true配置,初始化后不会自动播放,仅在点击按钮时触发 - 把移除
_active类的逻辑放到onReverseComplete回调中,等反向动画完全播放结束后再隐藏菜单 - 新增点击拦截逻辑,避免动画播放过程中重复点击导致的状态错乱
- 正向播放时指定从时间线起始位置
0开始,保证每次打开菜单的动画都是完整的入场效果
内容的提问来源于stack exchange,提问作者Summersby
相关产品推荐
相关产品推荐

