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

实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:36:12