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

使用anime.js实现树叶飘落动画:滚动回顶部无法重复触发问题求助

解决anime.js树叶飘落动画仅触发一次的问题

嘿,我明白你遇到的困扰了——滚动到顶部时树叶飘落动画只跑一次,再滚回来就没反应了对吧?这大概率是因为动画结束后元素的状态没重置,或者滚动触发的逻辑没处理好,咱们一步步来搞定它!

常见问题原因

  • 动画完成后,树叶的位置、透明度等属性停留在了动画结束的状态,下次触发时anime.js觉得没有需要变化的属性,就不执行了
  • 滚动事件的监听逻辑没有判断动画是否正在运行,或者只绑定了一次触发条件
  • 动画实例只创建了一次,运行完成后就处于结束状态,不会自动重启

解决方案代码示例

先给你一套完整的可运行代码,咱们边看边解释:

<!-- 假设你的HTML里有多个树叶元素 -->
<div class="leaf" style="position: fixed; top: 0; width: 30px; height: 30px; background: #8BC34A; border-radius: 50% 0;"></div>
<div class="leaf" style="position: fixed; top: 0; width: 25px; height: 25px; background: #CDDC39; border-radius: 50% 0;"></div>
<div class="leaf" style="position: fixed; top: 0; width: 35px; height: 35px; background: #FFC107; border-radius: 50% 0;"></div>
// 1. 初始化所有树叶的初始状态
const leaves = document.querySelectorAll('.leaf');
leaves.forEach(leaf => {
  // 把树叶放到屏幕上方不可见的位置,透明度设为0
  anime.set(leaf, {
    translateY: -100,
    opacity: 0,
    rotate: () => anime.random(-30, 30), // 初始随机旋转角度
    left: () => anime.random(10, window.innerWidth - 40) // 初始随机水平位置
  });
});

// 用一个标志位防止动画叠加运行
let isAnimating = false;

// 2. 滚动监听函数:判断是否滚动到顶部且无动画在运行
function handleScroll() {
  if (window.scrollY === 0 && !isAnimating) {
    isAnimating = true;
    startLeafFall();
  }
}

// 3. 核心动画函数
function startLeafFall() {
  anime({
    targets: '.leaf',
    translateY: window.innerHeight + 100, // 落到屏幕下方
    opacity: [0, 1, 0], // 先出现再消失
    rotate: () => anime.random(-180, 180), // 飘落时随机旋转
    duration: () => anime.random(3000, 6000), // 每个树叶飘落时长随机
    delay: () => anime.random(0, 2000), // 每个树叶延迟飘落
    easing: 'easeInOutQuad',
    complete: () => {
      // 动画结束后重置所有树叶的状态,为下次触发做准备
      leaves.forEach(leaf => {
        anime.set(leaf, {
          translateY: -100,
          opacity: 0,
          rotate: () => anime.random(-30, 30),
          left: () => anime.random(10, window.innerWidth - 40)
        });
      });
      // 标记动画已结束,允许下次触发
      isAnimating = false;
    }
  });
}

// 绑定滚动事件
window.addEventListener('scroll', handleScroll);

// 页面加载完成时,如果已经在顶部,自动触发一次动画
window.addEventListener('load', () => {
  if (window.scrollY === 0) {
    startLeafFall();
  }
});

关键要点解释

  • 重置元素状态:用anime.set()在动画开始前和结束后统一设置树叶的初始状态,确保每次触发动画时,元素都有明确的起始属性可以过渡
  • 防止动画叠加:isAnimating标志位避免用户快速滚动时多次触发动画,导致页面卡顿
  • 动态随机属性:每个树叶的位置、旋转角度、时长都用随机值,让飘落效果更自然

其他可能的排查方向

如果上面的代码还解决不了你的问题,可以检查:

  • 是否给树叶元素设置了正确的定位(比如position: fixed或absolute),否则translateY可能不会生效
  • 有没有其他JS代码修改了树叶的属性,干扰了anime.js的动画状态
  • 是否误用了anime.timeline()且没有重置时间线的进度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:35:05