如何实现多小球依次动画的CSS序列循环播放?
实现小球动画循环播放的解决方案
问题描述
现有一段CSS+HTML代码,实现了4个小球依次执行一次动画的序列,但当前仅能播放一次,需要实现以下循环效果:
- 序列开始
- 小球1执行一次动画
- 延迟1秒
- 小球2执行一次动画
- 延迟1秒
- 小球3执行一次动画
- 延迟1秒
- 小球4执行一次动画
- 延迟1秒
- 序列从第一步重新开始
纯CSS解决方案
通过调整动画总周期与关键帧的时间占比,让整个序列在一个循环周期内完成,规避animation-delay仅首次生效的问题。
完整代码
<div class="ball" id="ball-1"></div> <div class="ball" id="ball-2"></div> <div class="ball" id="ball-3"></div> <div class="ball" id="ball-4"></div>
/* 总周期设为4秒,每个小球在对应1秒窗口内执行动画 */ @keyframes ball1 { 0% { transform: translateX(0px); opacity: 0%; } 6.25% { opacity: 100%; } 12.5% { transform: translateX(120px); opacity: 0%; } 12.51%, 100% { transform: translateX(120px); opacity: 0%; } } @keyframes ball2 { 0%, 25% { transform: translateX(0px); opacity: 0%; } 31.25% { opacity: 100%; } 37.5% { transform: translateX(160px); opacity: 0%; } 37.51%, 100% { transform: translateX(160px); opacity: 0%; } } @keyframes ball3 { 0%, 50% { transform: translateX(0px); opacity: 0%; } 56.25% { opacity: 100%; } 62.5% { transform: translateX(200px); opacity: 0%; } 62.51%, 100% { transform: translateX(200px); opacity: 0%; } } @keyframes ball4 { 0%, 75% { transform: translateX(0px); opacity: 0%; } 81.25% { opacity: 100%; } 87.5% { transform: translateX(240px); opacity: 0%; } 87.51%, 100% { transform: translateX(240px); opacity: 0%; } } .ball { background: black; width: 20px; height: 20px; border-radius: 20px; margin: 10px; animation-duration: 4s; animation-iteration-count: infinite; animation-timing-function: linear; } #ball-1 { animation-name: ball1; } #ball-2 { animation-name: ball2; } #ball-3 { animation-name: ball3; } #ball-4 { animation-name: ball4; }
核心逻辑:将总循环周期设为4秒,每个小球的动画仅在对应1秒时间段内执行,其余时间保持终点状态,实现自动循环序列。
JavaScript解决方案
通过监听动画结束事件,手动控制每个小球的触发时机,精准匹配需求的序列逻辑。
完整代码
<div class="ball" id="ball-1"></div> <div class="ball" id="ball-2"></div> <div class="ball" id="ball-3"></div> <div class="ball" id="ball-4"></div>
@keyframes ball1 { 0% { transform: translateX(0px); opacity: 0%; } 50% { opacity: 100%; } 100% { transform: translateX(120px); opacity: 0%; } } @keyframes ball2 { 0% { transform: translateX(0px); opacity: 0%; } 50% { opacity: 100%; } 100% { transform: translateX(160px); opacity: 0%; } } @keyframes ball3 { 0% { transform: translateX(0px); opacity: 0%; } 50% { opacity: 100%; } 100% { transform: translateX(200px); opacity: 0%; } } @keyframes ball4 { 0% { transform: translateX(0px); opacity: 0%; } 50% { opacity: 100%; } 100% { transform: translateX(240px); opacity: 0%; } } .ball { background: black; width: 20px; height: 20px; border-radius: 20px; margin: 10px; animation-duration: 1s; animation-iteration-count: 1; animation-fill-mode: forwards; }
const balls = [document.getElementById('ball-1'), document.getElementById('ball-2'), document.getElementById('ball-3'), document.getElementById('ball-4')]; const animations = ['ball1', 'ball2', 'ball3', 'ball4']; function playSequence() { let index = 0; function playNext() { if (index >= balls.length) { setTimeout(playSequence, 1000); return; } const ball = balls[index]; // 重置动画状态 ball.style.animation = 'none'; void ball.offsetWidth; ball.style.animation = `${animations[index]} 1s forwards`; // 动画结束后触发下一个 ball.addEventListener('animationend', function handler() { ball.removeEventListener('animationend', handler); index++; setTimeout(playNext, 1000); }, { once: true }); } playNext(); } // 启动序列 playSequence();
核心逻辑:逐个触发小球动画,监听动画结束事件,延迟1秒后播放下一个,全部完成后再延迟1秒重启序列,完全匹配需求步骤。
内容的提问来源于stack exchange,提问作者coce
相关产品推荐
相关产品推荐

