網頁動畫 - element.animate() 現已推出 Chrome 36 版

布蘭登 (Brendan Kenny)
Brendan Kenny

網路動畫曾是 JavaScript 省份,但隨著網路紛紛改採行動裝置,動畫則移到 CSS 來處理宣告語法,而最佳化瀏覽器也能運用動畫完成。行動裝置上 60 fps 始終是您的目標,因此不用為了有效率地顯示內容,瀏覽器再也不需要其他瀏覽器。

越來越多工具可以提升 JavaScript 導向動畫的執行效率,但堅持和懸浮動畫是宣告式動畫和命令式動畫的統合式,在決定動畫編寫方式時,要考量的是最清楚的程式碼,而非單一形式的程式碼,而非不同形式的程式碼。

網路動畫表示該呼叫,而它的第一個部分是在 Chrome 36 中以 element.animate() 的形式呈現。這個新函式可讓您完全使用 JavaScript 建立動畫,並以與任何 CSS 動畫或轉場效果一樣有效執行動畫 (事實上,從 Chrome 34 版開始,同一個網路動畫引擎驅動上述所有方法)。

這種語法簡單,而且曾經編寫 CSS Transition 或 Animation 時,應該熟悉其組成部分:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

這項新功能的最大優勢,在於我們過去必須跳出許多尷尬的疊加動畫,才能呈現流暢、無卡頓的動畫。

以去年聖誕老人追蹤器為例,我們期望持續下雪,並決定透過 CSS 為它製作動畫,讓效率超高

然而,我們想要根據場景本身和場景本身發生的事件,以動態方式挑選雪的水平位置,同時因為雪景的下降高度 (使用者的瀏覽器視窗高度),除非實際跑步,否則無從得知。這表示我們確實必須使用 CSS 轉場效果,因為在執行階段編寫 CSS 動畫的做法很快就會變得複雜 (還有數百個雪花意味著數百種新的樣式規則)。

因此採取下列做法,您應熟悉以下做法:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

金鑰位於「wait a frame」註解中。為了順利啟動轉換作業,瀏覽器必須確認元素位於起始位置。做法有很多種,最常見的方法之一,就是在強制瀏覽器計算版面配置的元素屬性中讀取其中之一,以確保該元素在轉換至結束位置之前知道該元素具有起始位置。這種方法可讓你更瞭解使用者對瀏覽器內部的瞭解,同時每次按下按鍵都會有髒亂的感覺。

相較之下,對等的 element.animate() 呼叫無法更清楚地指出真正的預期用途:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

不僅如此,還有許多選擇。就像 CSS 供應商一樣,網路動畫可能會延遲並反覆發生:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

element.animate() 實際上會傳回 AnimationPlayer 物件,隨著更多網路動畫規格推出,動畫播放器也變得更重要。JavaScript 和 CSS 建立的動畫都會有相關聯的 AnimationPlayer,能夠以實用又有趣的方式完美結合。

不過,目前 AnimationPlayer 只有兩項功能,都非常實用。您隨時可以使用 AnimationPlayer.cancel() 取消動畫:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

同時,如果有人曾試圖以 CSS 動畫或轉場效果建構動畫系統,網路動畫一律會在完成時觸發事件:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

立即體驗

這一切都是 Chrome 36 的運送功能,我們今天將遷移至 Beta 版!如想試用這項功能,請嘗試在 Chrome 36 中採用原生實作方式。不過,網路動畫 polyfill 大幅放大了完整網路動畫規格中的部分內容,適合任何新型瀏覽器。

您可以嘗試使用 element.animate()原生版本和 polyfill 的雪效果示範。

分享寶貴意見

不過,這是即將推出的預先發布版,我們會特別發布,以便立即取得開發人員的意見回饋。我們目前還無法確定是否已達到所有用途,或從目前使用動畫 API 的粗略中穿梭。我們唯一的方式就是讓開發人員試用,並告訴我們他們的意見。

這篇文章中的評論很重要,而標準本身的意見也可透過 public-fx 郵寄清單傳送至 CSS 和 SVG 工作群組。

更新,2014 年 10 月:Chrome 39 開始支援與控製播放相關的多種其他方法,例如 play()pause()reverse()。您也可以透過 currentTime 屬性,跳到動畫時間軸中的特定時間點。如要瞭解這項功能的實際運作情形,請參閱這個新的示範模式

感謝 Addy Osmani 和 Max Heinritz 的協助。