Chromium 84 中的 Web Animations API 改良項目

利用承諾來自動化調度管理動畫、利用可替換的動畫提升效能,使用複合模式讓動畫更流暢等等。

Kevin Ellis
Kevin Ellis

發布日期:2020 年 5 月 27 日

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

Web Animations API 是一項工具,可讓開發人員使用 JavaScript 編寫命令式動畫。其目的,是要固定 CSS 動畫和轉換實作,以利開發未來效果,以及對現有效果進行組合和計時。

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

Web Animations API 在 2014 年 7 月 36 版首次中點擊 Chromium。這項規格將在 2020 年 7 月推出的第 84 版中完成。
Chromium 中 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 的後續規劃

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