如何控制 一個(gè)動(dòng)畫完成再執(zhí)行下一個(gè)動(dòng)畫

一、純 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 的方案。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容