js利用H5的requestAnimationFrame()API實現動畫效果
newbeehh發表於2018-06-20
為什麼要使用requestAnimationFrame:
- 我們知道,瀏覽器實現動畫繪製無非就是CSS3的動畫屬性
transition
,aniamtion
和JavaScript的setTImeOut
和setInterval
方法(進行DOM的樣式迴圈改變達到動畫效果)。說到這可能很多同學都有疑問了,既然有CSS的動畫屬性這麼方便的東西了,為何還要用setTimeOut
等js方法這麼麻煩呢?我們首先來解決這個疑問。
- CSS3的動畫屬性與JavaScript的動畫方法:
- 一個事物的存在必有其存在的道理,api也不例外,不然早被淘汰了。首先CSS3的動畫屬性是存在相容問題的,最明顯的就是IE10之後才相容。而目前主流的向下相容的標準還是要達到IE9的,所以
setTImeOut
等js方法還是主流的動畫解決方案。 - 有些動畫效果CSS3無法實現,如改變元素
scrollTop
的值進行滾動,這樣就只能使用js的相關方法了。 - CSS3的動畫無法實現過於複雜的動畫效果,如CSS3支援控制動畫速度賽貝爾曲線的數值有限,更復雜的動畫效果得使用js結合相關演算法才能完成
- 接著回到正題哈, 那
requestAnimationFrame
有setTimeOut
和setInterval
又有和區別呢,嗯,接下來就是正題了。
setTimeOut
和setInterval
出現的問題:
- 首先,我們得知道動畫的渲染是一幀一幀的進行的,每一幀就是動畫的一個靜止狀態,每一幀連起來就成為了一個動畫。因此每一幀的時間間隔要足夠短動畫才顯得平滑流暢,但每一幀又不能間隔得太短,因為瀏覽器每一秒的渲染能是有限的,而且螢幕的重新整理能力也是有限的,大多數的顯示器重新整理頻率是60H也就是每秒60幀,因此瀏覽器的重繪頻率不會超過顯示器的重新整理頻率。
- 所以每一幀大約17秒就是最佳的重繪間隔。那使用就直接使用
setTimeOut
或者setInterval
,間隔設定為17不就得了?但這樣還是不行的。 - 因瀏覽器的毫秒不精確:瀏覽器的計時器精度並非精確到毫秒級的,IE8的精確度是15ms多一點,而IE9等大多數的瀏覽器精確度都在4ms差不多。所以難以保證動畫最佳的時間間隔。
- 不同的瀏覽器渲染能力不同,因此並非每一幀17ms就是最佳渲染間隔。
- 在不需要動畫的地方,如後臺標籤頁,動畫任然在執行,消耗CPU的效能。
- 因此,h5的
requestAnimationFrame
就是解決以上問題的。
- requestAnimationFrame的特點:
requestAnimationFrame
會把每一幀中所有的DOM操作集中起來,在一次重繪或者重排中就完成。
requestAnimationFrame
重繪或者重排的時間間隔是系統的時間間隔,因為不同的瀏覽器的系統時間間隔不同,requestAnimationFrame
將會保持最佳的繪製間隔,即不會因為繪製間隔時間過短而造成瀏覽器渲染能力跟不上,也不會因為繪製間隔時間過長,而造成動畫卡頓。這樣就能在不同的瀏覽器中實現最佳的繪製效果。
- 在隱藏或者不可見的元素中,
requestAnimationFrame
將不會進行重排或者重繪,而執行在頁面沒有啟用的情況下,如requestAnimationFrame
執行在後臺標籤頁中,動畫將會暫停,有效的節省了CPU的開銷。
- 那麼,該如何使用
requestAnimationFrame
呢?
requestAnimationFrame的具體使用:
requestAnimationFrame
使用非常簡單,只需傳入改變DOM的函式,然後反覆呼叫requestAnimationFrame
即可達到動畫效果了。requestAnimationFrame返回一個整數型請求id的,可以用cancelAnimationFrame
函式去取消傳入requestAnimationFrame
的回撥函式。具體使用可以看MDN的教程。
後話: