Chromium 84 中的 Web Animations API 改良項目

運用承諾來協調動畫、透過可替換的動畫提升效能,以及使用複合模式讓動畫更流暢等等。

Kevin Ellis
Kevin Ellis

只要使用得當,動畫可以提升使用者對品牌的觀感和記憶、引導使用者採取行動,並協助使用者在數位空間中瀏覽您的應用程式。

Web Animation API 這項工具可讓開發人員使用 JavaScript 編寫動畫動畫。這個 API 旨在奠定 CSS 動畫和轉場效果的導入基礎,方便開發日後的特效,也能設計日後的組合效果和定時性。

雖然 FirefoxSafari 已經導入完整的規格功能,但 Chromium 84 仍將先前不支援的功能導入 Chrome 和 Edge,進一步實現跨瀏覽器互通性。

Web Animations API 於 2014 年 7 月 36 日首次命中 Chromium。現在規格內容已告一段落,第 84 版將於 2020 年 7 月生效。
Chromium 中 Web Animations API 的悠久歷史。

開始使用

如果您曾使用 @keyframe 規則,透過 Web Animation API 建立動畫的方式應會很熟悉。首先必須先建立一個主要畫面格物件在 CSS 中,看起來可能會像這樣:

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

在 JavaScript 中看起來會像這樣:

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

您可在 CSS 中設定動畫參數的位置:

.modal {
  animation: openAnimation 1s 1 ease-in;
}

則應在 JS 中設定:

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

程式碼數量大致相同,但只要搭配 JavaScript,就算只使用 CSS 也不例外。這包括設定順序效果,以及加強控制其播放狀態。

element.animate()之後

不過,經過更新後,Web Animations API 不再僅限於透過 element.animate() 建立的動畫。我們也可以操控 CSS 動畫和轉場效果。

getAnimations() 是一種方法,會傳回元素中的所有動畫,不論元素是透過 element.animate() 還是透過 CSS 規則 (CSS 動畫或轉換) 建立。其外觀範例如下:

首先,"get" 做為轉場效果的主要畫面格,用來決定轉換來源。接著,建立兩個新的不透明度動畫,啟用交叉淡出效果。交叉淡出效果完成後,即可刪除副本。

依承諾編排動畫

在 Chromium 84 中,您現在有 animation.readyanimation.finished 這兩種承諾使用的方法。

  • animation.ready 可讓您等待待處理的變更生效,也就是切換播放和暫停等播放控制項方法。
  • animation.finished 可讓您在動畫結束時執行自訂 JavaScript 程式碼。

讓我們繼續使用範例,並使用 animation.finished 建立自動化調度管理的動畫鏈結。在本例中,這是垂直轉換 (scaleY),後面接著水平轉換 (scaleX),然後是子項元素的不透明度變更:

將變形和透明度套用至開啟的互動視窗元素。查看 Codepen 的示範內容
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

我們先使用 animation.finished.then() 鏈結這些動畫,然後才執行鏈結中的下一個動畫集。這樣一來,動畫就會按順序顯示,您甚至可以對不同的目標元素套用不同的選項設定 (例如速度和容易)。

在 CSS 中,重新建立會相當麻煩,特別是將不重複且連續的動畫套用至多個元素時。您必須使用 @keyframe、排序正確的時間百分比才能放置動畫,並使用 animation-delay 才能依序觸發動畫。

例:播放、暫停及倒轉

可以開啟的東西,應該就能關閉了!幸好,自 Chromium 39 起,Web Animation API 讓我們可以播放、暫停及反轉動畫。

您可以擷取上述動畫,然後使用 .reverse() 再次點選該按鈕時,呈現流暢、反向的動畫。如此一來,您可以為我的互動視窗提供更順暢、更符合情境的互動功能。

當使用者按下按鈕時,會開啟和關閉的情況示例。查看 Glitch 示範

您可以建立兩個待播放的動畫 (openModal 和內嵌不透明度轉換),然後暫停其中一個動畫,並延後其中一個動畫,直到另一個動畫完成為止。然後,您可以使用承諾,等待每個項目都結束之後,再開始玩。最後,您可以查看是否已設定旗標,然後反轉每個動畫。

範例:與部分主要畫面格的動態互動

「指定舊訪客」範例:在使用者按下滑鼠後,系統會將動畫調整為新的位置。查看 Glitch 示範
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

在這個範例中,只有一個主要畫面格,沒有指定起始位置。以下示範如何使用部分主要畫面格。滑鼠處理常式會執行下列作業:設定新的結束位置並觸發新的動畫。系統會從目前的基礎位置推斷新的起始位置。

你可以在現有的轉場效果執行期間觸發新的轉場效果。這表示目前的轉換作業已中斷,並建立新的轉換。

利用可替換的動畫提升效能

根據事件 (例如 'mousemove') 建立動畫時,每次都會建立新的動畫,藉此快速消耗記憶體並降低效能。為解決這個問題,Chromium 第 83 版推出可替換的動畫,藉此啟用自動清理功能,將結束的動畫標記為可替換,並在其他已結束的動畫替換為其他播放完畢的動畫時,自動移除。請參考以下範例:

滑鼠移動時,幽默路徑會以動畫呈現。查看 Glitch 示範
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

每次滑鼠移動時,瀏覽器會重新計算小工具軌跡中每球的位置,並為這個新的點建立動畫。瀏覽器現在知道在下列情況中會移除舊動畫 (啟用替換功能):

  1. 動畫結束。
  2. 在複合順序中,有一個或多個動畫也已完成。
  3. 新動畫是為相同的屬性建立動畫效果。

您可以使用 anim.onremove 觸發計數器,找出每個已移除動畫的計數器,即可確切查看取代的動畫數量。

以下還有幾種方法可進一步控制動畫控制項:

  • animation.replaceState() 可讓您追蹤動畫為使用中、保留或已移除。
  • animation.commitStyles() 會根據基礎樣式,以及在複合順序中更新元素的所有動畫。
  • animation.persist() 會將動畫標示為無法取代。

使用複合模式,讓動畫更流暢

透過 Web Animations API,您現在可以設定動畫的複合模式,除了預設的「replace」模式之外,動畫形式可以是累加或累積。複合模式可讓開發人員編寫不同的動畫,並控管效果的組合方式。系統現在支援三種複合模式:'replace' (預設模式)、'add''accumulate'

建立複合動畫時,開發人員可以撰寫簡短而獨特的效果,然後再將這些動畫組合在一起。在以下範例中,我們會對每個方塊套用旋轉和縮放主要畫面格,但只有一個調整是複合模式,以下新增選項:

顯示預設、新增及累積複合模式的試用版。查看 Glitch 示範

在預設的 'replace' 複合模式中,最終動畫會取代轉換屬性,結尾為 rotate(360deg) scale(1.4)。如果是 'add',複合會新增旋轉並將比例乘上,進而產生 rotate(720deg) scale(1.96) 的最終狀態。'accumulate' 會合併轉換,因而產生 rotate(720deg) scale(1.8)。如要進一步瞭解這些複合模式的細節,請參閱網頁動畫規格中的 CompositeOperation 和 CompositeOperationOrAuto 列舉

一起來看看 UI 元素範例:

彈跳下拉式選單,其中套用了兩個合成動畫。查看 Glitch 示範

這裡有兩個 top 動畫完成合成。第一種是巨集動畫,它將下拉式選單本身高度移動,就像從頁面頂端滑入的動作效果,呈現在第二層動畫效果;第二是微動畫,當點擊向底部時,則會出現一點彈跳的彈跳效果。使用 'add' 複合模式可使轉場效果更順暢。

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

Web Animation API 的下一步

這些新功能現在都在瀏覽器中新增動畫功能,管道即將推出更多新增功能。以下將進一步說明未來的規格資訊: