使用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
相关产品推荐
相关产品推荐

