深入探究使JavaScript動畫流暢的一些方法_javascript技巧

來源:互聯網
上載者:User

基於Javascript的動畫暗中同CSS過渡效果一樣,甚至更加快,這怎麼可能呢?而Adobe和Google持續發布的富媒體移動網站的效能可媲美本地應用,這又怎麼可能呢?

本文逐一遍覽了基於Javascript的DOM動畫庫,如Velocity.js和GSAP,看其是如何比jQuery和CSS動畫效果更具效能的.
jQuery

讓我們先從基礎的開始: JavaScript 和 jQuery 被錯誤的混為一談了. JavaScript 動畫是很快的. jQuery 把它放慢了下來。為什嗎?因為 — 儘管jQuery非常強大 — 但成為一個效能強勁的動畫引擎從來都不是jQuery的設計目標:

  •     jQuery 不能避免 布局顛簸 ,這得歸因於它的程式碼程式庫提供了動畫之外的多種用途.
  •     jQuery 的記憶體消耗經常會觸發記憶體回收,那樣會 時不時的讓動畫定格下來.
  •     jQuery 使用 setInterval 而不是 requestAnimationFrame (RAF) 來 保護新技術不受其自身的影響.

應該注意到布局顛簸就是在動畫開始部分的不順暢,記憶體回收就是造成動畫期間不順暢的元兇, 而沒有使用RAF則會導致低幀率.

實現樣本

避免造成布局顛簸的DOM查詢和更新群組合:
 

var currentTop,  currentLeft; /* With layout thrashing. */currentTop = element.style.top; /* QUERY */element.style.top = currentTop + 1; /* UPDATE */ currentLeft = element.style.left; /* QUERY */element.style.left = currentLeft + 1; /* UPDATE */ /* Without layout thrashing. */currentTop = element.style.top; /* QUERY */currentLeft = element.style.left; /* QUERY */ element.style.top = currentTop + 1; /* UPDATE */element.style.left = currentLeft + 1; /* UPDATE */

發生在更新之後的查詢會強制瀏覽器對頁面的計算式資料進行重新計算 (同時會把新的更新效果考慮在內). 這樣就會對動畫產生顯著的開銷,而這隻是16毫秒微小間隔的運行逾時.

類似的,實現 RAF 並不必須是對你的現有程式碼程式庫的顯著返工. 讓我們拿RAF的基礎實現同setInterval比較一下:
 

var startingTop = 0; /* setInterval: Runs every 16ms to achieve 60fps (1000ms/60 ~= 16ms). */setInterval(function() {  /* Since this ticks 60 times a second, we divide the top property's increment of 1 unit per 1 second by 60. */  element.style.top = (startingTop += 1/60);}, 16); /* requestAnimationFrame: Attempts to run at 60fps based on whether the browser is in an optimal state. */function tick () {  element.style.top = (startingTop += 1/60);} window.requestAnimationFrame(tick);

RAF 產生了推動動畫效能的最大可能性,你可以對你的代碼進行單一的變更.

CSS 轉換

CSS轉換通過把動畫邏輯甩給瀏覽器本身去處理而超越了jQuery,這在以下幾方面是有效果的:(1)最佳化DOM互動和記憶體消耗以避免卡頓(顛簸),(2)利用引擎的RAF原則,(3)強制硬體加速(利用GPU的能力來提高動畫效能)。

然而,現實是,這些最佳化也可以在JavaScript中直接執行。GSAP已經這樣做了多年。Velocity.js,一個新的動畫引擎,不僅利用了同樣的技術,而且還向前多走了幾步——我們不久會探討這些。

面對事實,JavaScript動畫可以與CSS轉換競爭只是我們康複計劃的第一步。第二步是實現“JavaScript動畫實際上可以比CSS轉換更快”。


現在我們開始談談CSS變換的弱點:

  •     transition強制硬體加速會加大GPU消耗,高負荷情形下將導致運行不流暢。這種情況在行動裝置上尤為明顯。(特殊情況下,比如當資料在瀏覽器主線程和排版線程之間傳遞產生的瓶頸也會導致不流暢)。某些CSS屬性,比如transform和opacity,則不受這些瓶頸影響。Adobe在這裡精心總結了這些問題。
  •     transition在IE10以下沒有用,造成的自IE8和IE9以來的案頭網站可用性問題至今仍然廣泛存在。
  •     由於transition並不是由JavaScript原生控制(而僅僅是由JavaScript觸發),瀏覽器無法獲知如何與控制這些transition的JavaScript代碼同步地最佳化他們。

相反的,基於JavaScript的動畫庫則可以自行確定合適開啟硬體。它們原生支援各版本IE瀏覽器,並且它們尤其適合批量動畫最佳化。

我的建議是僅當你單獨為移動端開發且僅實現簡單動畫時使用原生CSS變換。這種環境下,transition是一種原生有效解決方案,可以使你在樣式表中實現所有動畫邏輯,而不用添加額外的JavaScript庫,從而避免你的頁面變得臃腫。然而,當你在設計複雜的UI,或者是開發存在不同狀態的UI的App時,你就應該使用動畫庫以使動畫保持流暢,同時使工作流程易於管理。Transit是一個在管理CSS變換方面做得尤其優秀的庫。

JavaScript 動畫

好了,那JavaScript可就在效能方面佔據上風了. 但Javascript究竟具體快了多少呢? 好吧 — 最初 — 對於構建一個實在的 3D動畫樣本 是足夠快的,通常在構建中你只會看到有使用WebGL. 而構建一個 多媒體小動畫 也夠了,通常你看到只會使用Flash或者After Effects構建. 而構建一個 虛擬世界 也夠了,通常你只會看到使用canvas構建.

為了對領先的動畫庫,當然還要包含Transit(它使用CSS漸層效果),進行直接的對比, 回頭去看看Velocity在VelocityJS.org上的文檔.

問題仍然是: JavaScript是怎樣具體的達成其高水平效能的? 下面是對基於Javascript動畫能夠被執行這一目標的最佳化的一個簡短清單:

  •     同步 DOM → 在整個動畫鏈中間入棧以最小化布局抖動.
  •     為整個鏈式調用緩衝屬性值,以最小化DOM查詢發生 (這些就是高效能DOM動畫的坑).
  •     在同樣的調用中緩衝整個同層級元素的單元轉換率 (比如 px 到 %, em, 等等.).
  •     當更新可能會在視覺上不可見時跳過樣式更新.


回顧一下我們先前學過的關於布局顛簸的知識,Velocity.js利用這些最佳實務來緩衝動畫結束值以複用為隨後動畫的開始值,從而避免了重新查詢DOM以擷取元素的開始值:
 

$element  /* Slide the element down into view. */  .velocity({ opacity: 1, top: "50%" })  /* After a delay of 1000ms, slide the element out of view. */  .velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });

在上面例子中,第二個 Velocity 調用知道它應該自動從 opacity為1 和 top為50% 開始。

瀏覽器本身最終能夠執行許多這些相同的最佳化,但這樣做會明顯減少開發人員能夠製作的動畫代碼的方式。因此,出於同樣原因,由於jQuery不使用RAF(如上所述),瀏覽器就不會強制最佳化它,甚至給出一個很小的機會去打破規格或偏離預期的行為。

最後,我們對這兩個JavaScript動畫庫(Velocity.js 和 GSAP)互相比較一下。


GSAP 是首個動畫庫,用在示範JavaScript DOM 令人印象深刻的動畫表現。它確實是這樣,但有些缺點:

  •     在中到高負荷動畫中,GSAP 的 DOM 互動開銷導致動畫在開始時和過程中失幀。
  •     相反於Velocity.js 是在超寬鬆的 MIT 許可下發布的,  GSAP 是閉源的, 並且在很多類商用時候需要許可年費。
  •     因為 GSAP 是一個完整的動畫套件,是 Velocity 大小的三倍。然而,GSAP 有如此豐富功能,有助於其成為動畫的瑞士軍刀。

我推薦做法是在你需要精確控制定時(比如 重繪,暫停/恢複)和運動(比如貝茲路徑路徑)的時候用 GSAP 。這些特性在遊戲開發和某些特殊應用中是至關重要的,但是通常不需要用在網頁應用的 UI中。

Velocity.js

引用 GSAP 豐富的特性並不代表Velocity自身在特性上是輕量級的. 相反,在壓縮後僅有的7kb中,Velocity不僅僅複製了jQuery $.animate()的所有功能, 它還把顏色動畫,轉換,迴圈,easing效果,類動畫還有滾動都打包了進去.

總之,Velocity是jQuery,jQuery UI,以及CSS漸層效果的最佳組合.

此外,從便利的角度看,Velocity在hood(蓋子,大概意思是公用的介面)之下使用jQuery的 $.queue() 方法, 如此就可以實現同 jQuery 的 $.animate(), $.fade(), 和 $.delay() 函數的無縫互操作. 而且,由於Velocity的文法同 $.animate() 的文法是相同的, 你不需要改變頁面的任何代碼.

讓我們快速地來看一看 Velocity.js. 在基礎的層面,Velocity的行為同$.animate()一樣:

 $element  .delay(1000)  /* Use Velocity to animate the element's top property over a duration of 2000ms. */  .velocity({ top: "50%" }, 2000)  /* Use a standard jQuery method to fade the element out once Velocity is done animating top. */  .fadeOut(1000);

在其最進階的層面,可以建立帶有3D動畫的複雜滾動情境 — 幾乎只要用到兩行簡單的代碼:
 

$element  /* Scroll the browser to the top of this element over a duration of 1000ms. */  .velocity("scroll", 1000)  /* Then rotate the element around its Y axis by 360 degrees. */  .velocity({ rotateY: "360deg" }, 1000);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.