一、純 CSS 方案(利用 animationend 事件)
通過監(jiān)聽動(dòng)畫結(jié)束事件 animationend,觸發(fā)下一個(gè)動(dòng)畫。
<div class="box" id="box1">動(dòng)畫1</div>
<div class="box" id="box2">動(dòng)畫2</div>
.box {
width: 100px;
height: 100px;
opacity: 0;
}
/* 初始隱藏 */
#box1 { background: red; }
#box2 { background: blue; }
/* 動(dòng)畫定義 */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
const box1 = document.getElementById('box1');
const box2 = document.getElementById('box2');
// 監(jiān)聽第一個(gè)動(dòng)畫結(jié)束
box1.addEventListener('animationend', () => {
box2.style.animation = 'fadeIn 1s forwards'; // 觸發(fā)第二個(gè)動(dòng)畫
});
// 啟動(dòng)第一個(gè)動(dòng)畫
box1.style.animation = 'fadeIn 1s forwards';
二、Web Animations API(現(xiàn)代瀏覽器)
利用 finished Promise 控制動(dòng)畫隊(duì)列。
const box1 = document.getElementById('box1');
const box2 = document.getElementById('box2');
// 定義動(dòng)畫
const animate1 = box1.animate(
[{ opacity: 0 }, { opacity: 1 }],
{ duration: 1000 }
);
// 第一個(gè)動(dòng)畫完成后觸發(fā)第二個(gè)
animate1.finished.then(() => {
box2.animate(
[{ opacity: 0 }, { opacity: 1 }],
{ duration: 1000 }
);
});
三、CSS Transition + Promise(精確控制)
將 CSS 過渡包裝成 Promise。
function waitForTransition(element) {
return new Promise(resolve => {
element.addEventListener('transitionend', resolve, { once: true });
});
}
// 使用示例
const box = document.querySelector('.box');
// 第一個(gè)動(dòng)畫
box.style.transform = 'translateX(200px)';
box.style.transition = 'transform 1s';
waitForTransition(box).then(() => {
// 第二個(gè)動(dòng)畫
box.style.transform = 'translateY(200px)';
});
四、Async/Await 鏈?zhǔn)秸{(diào)用
用現(xiàn)代 JavaScript 語法組織動(dòng)畫隊(duì)列。
async function runAnimations() {
const box1 = document.getElementById('box1');
const box2 = document.getElementById('box2');
// 第一個(gè)動(dòng)畫
await box1.animate([{ opacity: 0 }, { opacity: 1 }], 1000).finished;
// 第二個(gè)動(dòng)畫
await box2.animate([{ opacity: 0 }, { opacity: 1 }], 1000).finished;
// 更多動(dòng)畫...
}
runAnimations();
五、GSAP 動(dòng)畫庫(專業(yè)級(jí)解決方案)
使用業(yè)界標(biāo)桿動(dòng)畫庫 GSAP 的時(shí)序控制。
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>
// 創(chuàng)建時(shí)間線
const tl = gsap.timeline();
// 鏈?zhǔn)秸{(diào)用動(dòng)畫
tl.to("#box1", { duration: 1, x: 200 })
.to("#box2", { duration: 1, y: 200 }, "+=0.5"); // 延遲 0.5 秒執(zhí)行

image.png
最佳實(shí)踐
簡(jiǎn)單動(dòng)畫序列 → 純 CSS + animationend 事件
現(xiàn)代瀏覽器項(xiàng)目 → Web Animations API + async/await
企業(yè)級(jí)復(fù)雜動(dòng)畫 → GSAP 時(shí)間線控制
關(guān)鍵點(diǎn):避免使用 setTimeout 控制動(dòng)畫時(shí)序(幀率不穩(wěn)定),優(yōu)先使用基于事件或 Promise 的方案。