实现div从上到下掉落动画,循环执行5次的技术求助
实现div依次掉落并重复5轮的动画方案
嗨,我明白你的需求了——要让5个div按顺序从上到下掉落,一个完全完成后再启动下一个,而且整个流程要重复5次对吧?我给你两种可行的方案,先从最灵活的JavaScript控制方案说起:
方案一:JavaScript + CSS 动画(推荐,易控制)
1. HTML 结构
先准备好5个要掉落的div,给它们统一的类名方便选择:
<div class="fall-container"> <div class="fall-item">Div 1</div> <div class="fall-item">Div 2</div> <div class="fall-item">Div 3</div> <div class="fall-item">Div 4</div> <div class="fall-item">Div 5</div> </div>
2. CSS 动画定义
先写好掉落的基础动画,让元素从视口外上方落到目标位置:
.fall-container { position: relative; min-height: 300px; /* 给容器足够高度放掉落的元素 */ } .fall-item { position: absolute; top: -50px; /* 初始在容器外上方 */ left: 50px; width: 100px; height: 50px; background: #42b983; margin: 10px 0; text-align: center; line-height: 50px; color: white; opacity: 0; /* 初始隐藏,动画开始时显示 */ /* 给每个div设置不同的最终位置,避免重叠 */ &:nth-child(1) { top: -50px; } &:nth-child(2) { top: -110px; } &:nth-child(3) { top: -170px; } &:nth-child(4) { top: -230px; } &:nth-child(5) { top: -290px; } } /* 定义掉落动画 */ @keyframes fall { 0% { opacity: 0; transform: translateY(0); } 10% { opacity: 1; } 100% { opacity: 1; transform: translateY(calc(100% + 60px)); /* 落到目标位置,错开每个div的位置 */ } } /* 触发动画的类 */ .falling { animation: fall 1s ease-in-out forwards; }
3. JavaScript 控制逻辑
核心是监听每个动画的结束事件,依次触发下一个元素,完成一轮后重置状态,重复5次:
const fallItems = document.querySelectorAll('.fall-item'); const totalItems = fallItems.length; const totalCycles = 5; // 要重复的总轮数 let currentItemIndex = 0; let currentCycle = 0; // 定义触发下一个元素动画的函数 function triggerNextFall() { if (currentCycle >= totalCycles) return; // 达到次数就停止 const currentItem = fallItems[currentItemIndex]; // 先重置元素状态(移除动画类,回到初始位置) currentItem.classList.remove('falling'); // 强制浏览器重绘,否则重新添加类不会触发动画 void currentItem.offsetWidth; // 添加动画类,开始掉落 currentItem.classList.add('falling'); // 监听动画结束事件 currentItem.addEventListener('animationend', function handleAnimationEnd() { currentItem.removeEventListener('animationend', handleAnimationEnd); // 移除监听避免重复触发 currentItemIndex++; if (currentItemIndex >= totalItems) { // 一轮完成,重置索引,循环次数+1 currentItemIndex = 0; currentCycle++; // 加个短暂延迟再开始下一轮,让用户看清一轮结束 setTimeout(triggerNextFall, 800); } else { // 继续触发下一个元素 triggerNextFall(); } }); } // 启动第一次动画 triggerNextFall();
关键细节解释
- 用
animationend事件确保前一个动画完全结束后再启动下一个,完美实现依次执行的效果。 - 重置元素状态时,用
void currentItem.offsetWidth强制浏览器重绘,否则直接移除再添加动画类不会重新触发动画(浏览器会优化掉重复的样式变更)。 - 给每个div设置了不同的初始和最终位置,避免掉落时重叠,你可以根据需求调整这些数值。
方案二:纯CSS 实现(适合简单场景)
如果不想用JS,也可以用CSS的animation-delay和animation-iteration-count来实现,但灵活性稍差:
.fall-item:nth-child(1) { animation: fall 1s ease-in-out 0s 5 forwards; /* 第1个立即开始,重复5次 */ } .fall-item:nth-child(2) { animation: fall 1s ease-in-out 1s 5 forwards; /* 第2个延迟1s开始,重复5次 */ } .fall-item:nth-child(3) { animation: fall 1s ease-in-out 2s 5 forwards; /* 延迟2s */ } .fall-item:nth-child(4) { animation: fall 1s ease-in-out 3s 5 forwards; /* 延迟3s */ } .fall-item:nth-child(5) { animation: fall 1s ease-in-out 4s 5 forwards; /* 延迟4s */ }
这种方式的缺点是:每一轮的间隔是固定的,而且如果动画时长调整,所有的delay都要手动修改;另外,元素是各自重复自己的动画,不是严格意义上的“一轮完成后再开始下一轮”(不过视觉效果类似)。
你可以根据自己的需求选择方案,推荐第一种JS控制的方式,逻辑更清晰,也更容易调整动画顺序、循环次数或者添加其他交互~
内容的提问来源于stack exchange,提问作者naveed ahmed
相关产品推荐
相关产品推荐

