Chromium 84 中的 Web Animations API 改良項目

透過承諾協調動畫、使用可替換動畫改善效能、使用合成模式讓動畫更流暢等等。

Kevin Ellis
Kevin Ellis

發布日期:2020 年 5 月 27 日

正確使用動畫可提升使用者對品牌的認知和記憶力,引導使用者採取行動,並協助使用者瀏覽應用程式,在數位空間中提供相關資訊。

Web Animations API 是一項工具,可讓開發人員使用 JavaScript 編寫命令式動畫。這項 API 的設計目的是支援 CSS 動畫和轉場實作,並可用於開發日後的效果,以及組合和設定現有效果的時間。

雖然 FirefoxSafari 已實作完整的規格功能,但 Chromium 84 為 Chrome 和 Edge帶來許多先前不支援的功能,可實現跨瀏覽器的互通性。

Web Animations API 首次出現在 2014 年 7 月的 Chromium 36 版。這項規格將在 2020 年 7 月推出的第 84 版中完成。
Chomeium 中 Web Animations API 的悠久歷史。

開始使用

如果您曾使用 @keyframe 規則,那麼使用 Web Animations 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 Animations API 就已提供播放、暫停和倒轉動畫的功能。

您可以使用 .reverse() 再次點選按鈕時,將先前顯示的動畫設為平滑的反向動畫。這樣一來,您就能為我們的模式建立更順暢且更符合情境的互動體驗。

按鈕點選後,模態視窗開啟和關閉的範例。在 Glitch 上查看示範

您可以建立兩個待播放的動畫 (openModal 和內嵌不透明度轉換),然後暫停其中一個動畫,延遲至另一個動畫完成。接著,您可以使用承諾,等待每個承諾完成後再播放。最後,您可以檢查是否已設定標記,然後反轉每個動畫。

範例:使用部分關鍵影格進行動態互動

重新定位範例:滑鼠點擊會將動畫調整至新位置。在 Glitch 上查看示範
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

在本範例中,只有一個關鍵影格,且未指定起始位置。以下是使用部分關鍵影格的範例。滑鼠處理常式會在此處執行幾項操作:設定新的結束位置,並觸發新的動畫。系統會根據目前的基礎位置推斷新的起始位置。

在現有轉場效果仍在執行時,您可以觸發新的轉場效果。這表示目前的轉場會中斷,並建立新的轉場。

透過可替換動畫改善效能

建立動畫時,如果是根據事件 (例如 on '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)。如要進一步瞭解這些合成模式的複雜性,請參閱 Web Animations 規格中的 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 Animations API 的後續發展

這些都是目前瀏覽器中令人興奮的動畫功能新增功能,而且未來還會有更多新增功能。請查看以下未來規格,進一步瞭解即將推出的功能: