利用承諾來自動化調度管理動畫、利用可替換的動畫提升效能,使用複合模式讓動畫更流暢等等。
發布日期:2020 年 5 月 27 日
正確使用動畫可提升使用者對品牌的認知和記憶力,引導使用者採取行動,並協助使用者瀏覽應用程式,在數位空間中提供相關資訊。
Web Animations API 是一項工具,可讓開發人員使用 JavaScript 編寫命令式動畫。其目的,是要固定 CSS 動畫和轉換實作,以利開發未來效果,以及對現有效果進行組合和計時。
雖然 Firefox 和 Safari 已實作完整的規格功能,但 Chromium 84 為 Chrome 和 Edge帶來許多先前不支援的功能,可實現跨瀏覽器的互通性。
開始使用
如果您曾使用 @keyframe
規則,那麼使用 Web Animations API 建立動畫應該會覺得很熟悉。首先,您需要建立關鍵影格物件。在 CSS 中,可能會像這個:
@keyframes openAnimation {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
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.ready
和 animation.finished
。
animation.ready
可讓您等待待變更生效 (也就是在播放和暫停等播放控制方法之間切換)。animation.finished
提供一種方法,可在動畫完成時執行自訂 JavaScript 程式碼。
接著,我們將繼續使用這個範例,並使用 animation.finished
建立協調的動畫鏈結。在這裡,您有一個垂直轉換 (scaleY
),後面接著水平轉換 (scaleX
),然後對子項元素產生不透明度:
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()
再次點選按鈕時,將先前顯示的動畫設為平滑的反向動畫。這樣一來,您就能為我們的彈出式視窗建立更順暢且更符合情境的互動體驗。
您可以建立兩個待播放的動畫 (openModal
和內嵌不透明度轉換),然後暫停其中一個動畫,延遲至另一個動畫完成。接著,你可以使用承諾,等待每項完成的練習後再演奏。最後,您可以檢查是否已設定標記,然後反轉每個動畫。
範例:與部分主要畫面格的動態互動
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
{duration: 1000, fill: 'forwards'});
在本範例中,只有一個關鍵影格,且未指定起始位置。以下是使用部分關鍵影格的範例。滑鼠處理常式會在此處執行幾項操作:設定新的結束位置,並觸發新的動畫。系統會根據目前的基礎位置推斷新的起始位置。
新的轉場效果可以在執行中時觸發。這表示目前的轉場會中斷,並建立新的轉場。
使用可替換動畫改善效能
建立以事件為依據的動畫 (例如 on 'mousemove'
) 時,每次都會建立新的動畫,這可能會快速耗用記憶體並降低效能。為解決這個問題,我們在 Chromium 83 中推出了可替換的動畫,以便自動清理,當已完成的動畫被標示為可替換,並在被其他已完成的動畫取代時自動移除。請參考以下範例:
elem.addEventListener('mousemove', evt => {
rectangle.animate(
{ transform: translate(${evt.clientX}px, ${evt.clientY}px) },
{ duration: 500, fill: 'forwards' }
);
});
每次滑鼠移動時,瀏覽器都會重新計算彗星軌跡中每個圓點的位置,並為這個新點建立動畫。現在,瀏覽器在下列情況知道移除舊動畫 (啟用取代動畫):
- 動畫已完成。
- 在組合順序中,有一個或多個動畫也已完成。
- 新動畫會為相同的屬性製作動畫。
您可以使用 anim.onremove
觸發計數器,並計算每個已移除的動畫,藉此查看目前取代的動畫數量。
以下還有幾種方法可以進一步使動畫控制項更臻完善:
animation.replaceState()
提供追蹤動畫是否處於作用中、持續或已移除的機制。animation.commitStyles()
會根據基礎樣式更新元素的樣式,以及元素上所有動畫的複合順序。animation.persist()
會將動畫標示為不可取代。
使用複合模式讓動畫更流暢
有了 Web Animations API,您現在可以設定動畫的複合模式,除了預設的「replace」模式外,還可以是加法或累加模式。合成模式可讓開發人員編寫獨特的動畫,並控管效果的組合方式。現已支援三種複合模式:'replace'
(預設模式)、'add'
和 'accumulate'
。
在合成動畫時,開發人員可以編寫短而獨特的效果,並查看這些效果的組合。在以下範例中,我們會為每個方塊套用旋轉和縮放關鍵影格,唯一調整的是加入做為選項的組合模式:
在預設的 'replace'
複合模式中,最終動畫會取代轉換屬性,直到 rotate(360deg) scale(1.4)
結束。針對 'add'
,組合函式會新增旋轉並乘上比例,最終狀態為 rotate(720deg) scale(1.96)
。'accumulate'
會結合轉換,產生 rotate(720deg) scale(1.8)
。如要進一步瞭解這些合成模式的複雜性,請參閱 Web Animations 規格中的 CompositeOperation 和 CompositeOperationOrAuto 列舉。
請參考下列 UI 元素範例:
這裡有兩個 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 的後續規劃
這些都是現今瀏覽器中令人興奮的動畫功能新增功能,而且未來還會有更多新增功能。請查看這些未來規格,進一步瞭解即將推出的功能: