透過承諾協調動畫、使用可替換動畫改善效能、使用合成模式讓動畫更流暢等等。
發布日期: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 的後續發展
這些都是目前瀏覽器中令人興奮的動畫功能新增功能,而且未來還會有更多新增功能。請查看以下未來規格,進一步瞭解即將推出的功能: