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

GSAP连续播放实现问题:单次执行限制与优化需求

解决GSAP Timeline仅能播放一次的问题

看起来你遇到的问题是GSAP的Timeline在第一次播放完成后,再次调用play()没有反应——这是因为Timeline播放结束后会停在**进度100%**的状态,默认的play()只会从当前进度继续,自然不会触发新的动画。而restart()虽然能重置播放,但可能因为立即重置元素初始状态导致视觉跳变,体验不佳。

下面是针对你代码的修正方案,能实现点击切换时,每次都从头完整播放对应的Timeline:

修正后的代码

let flag = true;
document.body.addEventListener("click", function () {
  // 先暂停当前可能正在运行的动画,避免状态冲突
  startGrap.pause();
  endGrap.pause();

  if (flag) {
    // 从进度0开始播放startGrap
    startGrap.play(0);
    flag = false;
  } else {
    // 从进度0开始播放endGrap
    endGrap.play(0);
    flag = true;
  }
});

// 直接用timeline的paused选项初始化,更简洁
const startGrap = gsap
  .timeline({ paused: true })
  .addLabel("start")
  .to(property, 0.5, { direction: -8.0, ease: "power2.out" })
  .to(property, 0.7, { direction: 0.0, ease: "back.out(3.0)" })
  .to(
    property,
    0.8,
    { offsetZ: 0.0, ease: "power3.inOut" },
    "start"
  );

const endGrap = gsap
  .timeline({ paused: true })
  .addLabel("start")
  .to(property, 0.4, { direction: -8.0, ease: "power2.out" })
  .to(property, 0.4, { direction: 0.0, ease: "back.out(4)" })
  .to(
    property,
    0.8,
    { offsetZ: -500.0, ease: "power3.inOut" },
    "start"
  );

关键改动说明

  1. play(0)替代play()
    GSAP的play()方法如果不带参数,会从Timeline当前的进度位置继续播放。当Timeline已经播放完成(进度为1),调用play()不会有任何反应。而play(0)会强制将Timeline的进度重置为0,然后从头开始播放,确保每次点击都能触发完整的动画序列。

  2. 播放前暂停其他动画
    增加startGrap.pause()endGrap.pause(),避免两个Timeline同时运行导致的元素状态冲突,尤其是在动画未完成时点击切换的场景下,能让过渡更平滑。

  3. 简化Timeline初始化
    直接在创建Timeline时添加{ paused: true }选项,替代后续的.pause()调用,代码更简洁易读。

这样修改后,你就能通过点击连续切换两个动画的播放,且每次都是完整的动画效果,不会出现只能执行一次的问题。

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

火山引擎 最新活动