透過承諾協調動畫、使用可替換動畫改善效能、使用合成模式讓動畫更流暢等等。
發布日期:2020 年 5 月 27 日
正確使用動畫可提升使用者對品牌的認知和記憶力,引導使用者採取行動,並協助使用者瀏覽應用程式,在數位空間中提供相關資訊。
Web Animations API 是一項工具,可讓開發人員使用 JavaScript 編寫命令式動畫。這項 API 的設計目的是支援 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 的後續規劃
這些都是現今瀏覽器中令人興奮的動畫功能新增功能,而且未來還會有更多新增功能。請參閱下列日後的規格,進一步瞭解後續規畫: