如何做出高大上的動畫效果?

當(dāng)我們要在頁面上實現(xiàn)一些動畫效果的時候,通常會考慮兩種方式:

1、通過css3的animation+keyframes,或者transition

2、通過setTimeout或者setInterval。

毫無疑問,首選的方案是第一種。而當(dāng)需要考慮兼容性,或者需要精確的控制動畫的時候,無可避免地會使用setTimeout/setInterval來實現(xiàn)動畫。這種實現(xiàn)方式是低效的,而且在當(dāng)前時間點,可以考慮更高效的實現(xiàn)方式。

什么是流暢

頁面的每一幀都是系統(tǒng)通過CPU或者GPU繪制出來的,其繪制的最高幀率受限于顯示器的刷新頻率。鑒于大多數(shù)的顯示器刷新頻率都是60Hz,頁面的最大繪制幀率就是60fps(frame per second)。

因此一個動畫最理想的情況就是60fps。這就意味著我們需要在把每一幀的繪制時間限制在16.7毫秒(1000/60),壓力山大。

setTimeout/setInterval的問題

首先,計時并不精確。setTimeout和setInterval的計時依賴瀏覽器內(nèi)置時鐘,而內(nèi)置時鐘的精確度又依賴于時鐘的更新頻率,在IE8及以下版本的瀏覽器中,這個更新頻率是15.6ms。也就意味著,如果把timer的間隔設(shè)成16.7ms,我們需要經(jīng)歷兩個時鐘更新周期才會觸發(fā)timer,延時了14.5ms(15.6 * 2 – 16.7)。

其次,由于單線程與異步隊列,當(dāng)動畫兩幀之間有一個復(fù)雜任務(wù)時,第二幀的繪制會一直等待這個任務(wù)完畢才會開始,必然會帶來卡頓現(xiàn)象。

假使計時是精確的(以14ms為例),任務(wù)隊列也不存在阻塞狀態(tài),是不是就沒問題了?我們看下圖,紅色幀丟失。

requestAnimationFrame

requestAnimationFrame

這里并不討論requestAnimationFrame的定義,具體可以看:

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame

從上面的描述中,我們可以總結(jié)出影響一個動畫的兩個關(guān)鍵因素:

1、開始繪制一幀的時機。

2、繪制一幀需要的時間。

requestAnimationFrame這個原生API可以自動幫我們設(shè)置動畫的幀率,我們只需要告訴它,我們需要繪制新的一幀,請在繪制下一幀的時候調(diào)用我的回調(diào)函數(shù)。這保證了上面的關(guān)鍵因素的第一點。對于第二點requestAnimationFrame是沒有辦法的,但是它可以在繪制時間比較長的時候,把動畫幀率從60fps變?yōu)?0fps以保證動畫不卡頓。

requestAnimationFrame還處于草案階段,瀏覽器的兼容性也有限:

Polyfill

requestAnimationFrame

不同的瀏覽器對于requestAnimationFrame定義存在差異,而且對于不支持該特性的瀏覽器,我們需要降級到setTimeout的方案。好在requestAnimationFrame和setTimeout的定義一致,比較方便做兼容。

兼容方法已經(jīng)有成熟的實現(xiàn)。

關(guān)于Layer

requestAnimationFrame

我們以Apple的主頁為例:

最上面的圖片輪轉(zhuǎn)動畫里,每一頁都設(shè)置了transform:translateZ(0px)。為什么可以使用2D渲染就能實現(xiàn)的效果卻要用3D?這就跟瀏覽器的渲染機制有關(guān)。

首先,使用3D的話,瀏覽器會調(diào)用GPU而不是CPU來進行頁面渲染,效率更高。

其次,瀏覽器渲染一個頁面的過程中,會把頁面元素分成若干的層(Layer),然后按層提交給GPU做貼圖渲染。當(dāng)我們要改變某一個DOM的樣式時,比如width或者h(yuǎn)eight,會觸發(fā)該DOM所在層的重繪。一次操作還好,但是如果是頻繁改變的動畫,效率就會非常低。

Apple這里使用translate3d,就是為了單獨為動畫頁建立Layer,進而提高重繪的效率。

總結(jié)

精度低的動畫盡量使用css3來實現(xiàn)。

如果需要js來實現(xiàn)動畫,可以使用requestAnimationFrame。有兼容需求可以引入polyfill。

盡量把動畫DOM放在獨立的Layer中。

本文作者:高原(點融黑幫),現(xiàn)任點融成都團隊高級前端開發(fā),四川大學(xué)計算機碩士。三年創(chuàng)業(yè),一年外企經(jīng)驗,專注于研究前端的各種框架與新技術(shù)。業(yè)余喜歡打籃球,司職中鋒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前言 本文主要參考w3c資料,從底層實現(xiàn)原理的角度介紹了requestAnimationFrame、cancelA...
    Bruce_zhuan閱讀 1,551評論 0 3
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,573評論 6 30
  • 動畫,顧名思義,就是能“動”的畫。人的眼睛對圖像有短暫的記憶效應(yīng),所以當(dāng)眼睛看到多張圖片連續(xù)快速的切換時,就會被認(rèn)...
    彬_仔閱讀 1,692評論 1 8
  • 一:在制作一個Web應(yīng)用或Web站點的過程中,你是如何考慮他的UI、安全性、高性能、SEO、可維護性以及技術(shù)因素的...
    Arno_z閱讀 1,232評論 0 1
  • 看了很多視頻、文章,最后卻通通忘記了,別人的知識依舊是別人的,自己卻什么都沒獲得。此系列文章旨在加深自己的印象,因...
    DCbryant閱讀 752評論 0 2