什么?你還不知道Web Animations API

JavaScript 中有一個用于動畫的原生 API,稱為 Web Animations API。在這篇文章中,我們將其稱為 WAAPI。
在本文中,我們將比較 WAAPI 和用 CSS 完成的動畫。
關于瀏覽器支持的說明
當代瀏覽器的支持是有限的,WAAPI 有一個全面和強大的?polyfill[1]?工具,使得它可以在生產(chǎn)環(huán)境下使用。polyfill 是 Web 動畫 API 的 JavaScript 實現(xiàn),它在本機不支持它的瀏覽器中提供 Web 動畫功能。當一個可用時,polyfill 回退到本機實現(xiàn)。
WAAPI基礎
如果您曾經(jīng)使用過 jQuery 的?.animate(),那么 WAAPI 的基本語法應該看起來很熟悉。
var element = document.querySelector('.animate-me');element.animate(keyframes, 1000);
該 animate 方法接受兩個參數(shù):關鍵幀和持續(xù)時間。與 jQuery 相比,它不僅具有內(nèi)置于瀏覽器的優(yōu)點,而且性能更高。
第一個參數(shù),關鍵幀,應該是一個對象數(shù)組。每個對象都是我們動畫中的關鍵幀。這是一個簡單的例子:
var keyframes = [{ opacity: 0 },{ opacity: 1 }];
第二個參數(shù),持續(xù)時間,是我們希望動畫持續(xù)多長時間。在上面的例子中,它是 1000 毫秒。讓我們看一個更令人興奮的例子。
使用 WAAPI 重新創(chuàng)建 animista CSS 動畫
這是 CSS 中的關鍵幀:
0% {transform: translateY(-1000px) scaleY(2.5) scaleX(.2);transform-origin: 50% 0;filter: blur(40px);opacity: 0;}100% {transform: translateY(0) scaleY(1) scaleX(1);transform-origin: 50% 50%;filter: blur(0);opacity: 1;}
這是 WAAPI 中的相同代碼:
var keyframes = [{transform: 'translateY(-1000px) scaleY(2.5) scaleX(.2)',transformOrigin: '50% 0', filter: 'blur(40px)', opacity: 0},{transform: 'translateY(0) scaleY(1) scaleX(1)',transformOrigin: '50% 50%',filter: 'blur(0)',opacity: 1}];
我們已經(jīng)看到將關鍵幀應用于我們想要動畫的任何元素是多么容易:
element.animate(keyframes, 700);為了使示例簡單,我只指定了持續(xù)時間。但是,我們可以使用第二個參數(shù)傳遞更多選項。至少,我們還應該指定一個緩動。以下是包含一些示例值的可用選項的完整列表:
var options = {iterations: Infinity,iterationStart: 0,delay: 0,endDelay: 0,direction: 'alternate',duration: 700,fill: 'forwards',easing: 'ease-out',}options);
緩動
緩動是任何動畫中最重要的元素之一。WAAPI 為我們提供了兩種不同的方式來設置緩動——在我們的關鍵幀數(shù)組中或在我們的選項對象中。
在 CSS 中,如果您應用了,animation-timing-function: ease-in-out 緩入緩出動畫。事實上,緩動應用于關鍵幀之間,而不是整個動畫。這可以對動畫的感覺進行細粒度的控制。WAAPI 也提供了這種能力。
var keyframes = [{ opacity: 0, easing: 'ease-in' },{ opacity: 0.5, easing: 'ease-out' },{ opacity: 1 }]
值得注意的是,在 CSS 和 WAAPI 中,您不應該為最后一幀傳遞緩動值,因為這將不起作用。這是很多人都會犯的錯誤。
有時在整個動畫上添加緩動更直觀。這在 CSS 中是不可能的,但現(xiàn)在可以通過 WAAPI 來實現(xiàn)。
var options = {duration: 1000,easing: 'ease-in-out',}
值得注意的是 CSS 動畫和 WAAPI 之間的另一個區(qū)別:CSS 的默認值是 ease,而 WAAPI 的默認值是 linear。
WAAPI 提供了與 CSS 動畫相同的性能改進,可以實現(xiàn)流暢的動畫,意味著我們 will-change 可以避免使用。
動畫對象
該?.animate()?方法不僅為我們的元素設置動畫,它還返回一些東西。
var myAnimation = element.animate(keyframes, options);
如果我們查看控制臺中的返回值,我們會看到它是一個動畫對象。這為我們提供了各種功能,其中一些功能一目了然,例如?myAnimation.pause(). 我們也可以通過更改?animation-play-state?屬性來使用 CSS 動畫實現(xiàn)類似的效果?element.style.animationPlayState = "paused". 我們還可以輕松地反轉我們的動畫?myAnimation.reverse()?。
使用 WAAPI,我們可以簡單地使用?myAnimation.play()?從頭開始播放動畫,如果它之前已經(jīng)完成,或者如果我們暫停它,則從中間迭代播放它。
我們甚至可以完全輕松地更改動畫的速度。
myAnimation.playbackRate = 2; // speed it upmyAnimation.playbackRate = .4; // use a number less than one to slow it down
獲取動畫
此方法將為我們返回 WAAPI 定義的任何動畫以及任何 CSS transitions 或者 animations 動畫。
element.getAnimations() // returns any animations or transitions applied to our element using CSS or WAAPI如果您覺得使用 CSS 來定義和應用動畫很舒服并且滿意,則?getAnimations()?允許您將 API 與@keyframes?結合使用。
即使一個 DOM 元素只應用了一個動畫,getAnimations()?也將始終返回一個數(shù)組。讓我們獲取要使用的單個動畫對象。
var h2 = document.querySelector("h2");var myCSSAnimation = h2.getAnimations()[0];
現(xiàn)在我們可以在我們的 CSS 動畫上使用 web 動畫 API 了 。
myCSSAnimation.playbackRate = 4;myCSSAnimation.reverse();
事件 promise
我們已經(jīng)有各種各樣的 CSS,我們可以在我們的 JavaScript 代碼利用觸發(fā)事件:? animationstart,animationend,animationiteration 和 transitionend。我經(jīng)常需要監(jiān)聽動畫或過渡的結束,然后從 DOM 中刪除它應用到的元素。
在 WAAPI 中使用 onfinish,與 animationend 或 transitionend 相同:
myAnimation.onfinish = function() {element.remove();}
WAAPI 為我們提供了使用事件和 promise 兩種選擇。?finished?我們的動畫對象的屬性將返回一個在動畫結束時解析的 promise。以下是使用 promise 的上述示例:
myAnimation.finished.then(() =>element.remove())
在這個例子中,只有在頁面上的所有動畫都完成后,我們的函數(shù)才會運行。
Promise.all(document.getAnimations().map(animation =>animation.finished)).then(function() {// do something cool})
References
[1]?polyfill:?https://github.com/web-animations/web-animations-js/tree/master
