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

如何解决不同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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:24:05