一文詳解requestAnimationFrame請求動畫幀
1.定義
它是一個瀏覽器的宏任務。 requestAnimationFrame的用法與setTimeout、setInterval很相似,只是不需要設置時間間隔而已。requestAnimationFrame使用一個回調函數(shù)作為參數(shù),這個回調函數(shù)會在瀏覽器重繪之前調用。它返回一個整數(shù),表示定時器的編號,這個值可以傳遞給cancelAnimationFrame用于取消這個函數(shù)的執(zhí)行。
2.特點
requestAnimationFrame特點: 、
【1】requestAnimationFrame會把每一幀中的所有DOM操作集中起來,在一次重繪或回流中就完成,并且重繪或回流的時間間隔緊緊跟隨瀏覽器的刷新頻率。
【2】在隱藏或不可見的元素中,requestAnimationFrame將不會進行重繪或回流,這當然就意味著更少的CPU、GPU和內存使用量。
【3】requestAnimationFrame是由瀏覽器專門為動畫提供的API,在運行時瀏覽器會自動優(yōu)化方法的調用,并且如果頁面不是激活狀態(tài)下的話,動畫會自動暫停,有效節(jié)省了CPU開銷
3.瀏覽器動畫原理
要真正理解requestAnimationFrame的優(yōu)勢首先要清楚瀏覽器動畫的基本實現(xiàn)思路。實際上就是在前端運行一個頻繁觸發(fā)的函數(shù),這個函數(shù)每次運行時都是更新物體的位置屬性,比如每次都沿X方向每次都會加1,當這個函數(shù)的觸發(fā)頻率足夠高,人眼就不會有任何察覺,因此顯示在屏幕上的效果就是流暢的動畫了。
4. CSS3動畫和JS動畫的比較
·CSS動畫優(yōu)點
【1】在Chromium基礎上的瀏覽器中
【2】同時CSS動畫不觸發(fā)layout或paint,在CSS動畫或JS動畫觸發(fā)了paint或layout時,需要main thread進行Layer樹的重計算,這時CSS動畫或JS動畫都會阻塞后續(xù)操作。
【3】部分情況下瀏覽器可以對動畫進行優(yōu)化(比如專門新建一個圖層用來跑動畫)。
【4】 部分效果可以強制使用硬件加速 (通過 GPU 來提高動畫性能)
·CSS動畫缺點
【1】代碼冗長。
【2】CSS 實現(xiàn)稍微復雜一點動畫,CSS代碼可能都會變得非常笨重; 運行過程控制較弱。
【3】css3動畫只能在某些場景下控制動畫的暫停與繼續(xù),不能在特定的位置添加回調函數(shù)。
·JS動畫優(yōu)點
【1】JS動畫控制能力強,可以在動畫播放過程中對動畫進行精細控制,如開始、暫停、終止、取消等;
【2】JS動畫效果比CSS3動畫豐富,功能涵蓋面廣,比如可以實現(xiàn)曲線運動、沖擊閃爍、視差滾動等CSS難以實現(xiàn)的效果;
【3】JS動畫大多數(shù)情況下沒有兼容性問題,而CSS3動畫有兼容性問題;
·JS動畫缺點
【1】JS在瀏覽器的主線程中運行,而主線程中還有其它需要運行的JS腳本、樣式計算、布局、繪制任務等,對其干擾可能導致線程出現(xiàn)阻塞,從而造成丟幀的情況;
【2】 對于幀速表現(xiàn)不好的低版本瀏覽器,CSS3可以做到自然降級,而JS則需要撰寫額外代碼;
【3】 JS動畫往往需要頻繁操作DOM的css屬性來實現(xiàn)視覺上的動畫效果,這個時候瀏覽器要不停地執(zhí)行重繪和重排,這對于性能的消耗是很大的,尤其是在分配給瀏覽器的內存沒那么寬裕的移動端。
5. setTimeout 、setInterval、requestAnimationFrame區(qū)別
1》setInterval
運行機制:
按照指定的周期(以毫秒計)來調用函數(shù)或計算表達式。方法會不停地調用函數(shù)(當頁面被隱藏或者最小化時,setInterval()仍在后臺繼續(xù)執(zhí)行,這種動畫刷新是完全沒有意義的,對cpu也是極大的浪費),直到 clearInterval() 被調用或窗口被關閉。 setinterval的執(zhí)行時間不確定,參數(shù)中的時間間隔是將代碼添加到異步隊列中等待的時間。只有當主線程中的任務以及隊列前面的任務是執(zhí)行完畢,才真正開始執(zhí)行動畫代碼。
缺點:
(1)setinterval()無視代碼錯誤,如果setinterval執(zhí)行的代碼由于某種原因出了錯,它還會持續(xù)不斷地調用該代碼。
(2)setinterval無視網(wǎng)絡延遲,由于某些原因(服務器過載、臨時斷網(wǎng)、流量劇增、用戶帶寬受限,等等),你的請求要花的時間遠比你想象的要長。但setinterval不在乎。它仍然會按定時持續(xù)不斷地觸發(fā)請求,最終你的客戶端網(wǎng)絡隊列會塞滿調用函數(shù)。
(3) setinterval不保證執(zhí)行,與settimeout不同,并不能保證到了時間間隔,代碼就準能執(zhí)行。如果你調用的函數(shù)需要花很長時間才能完成,那某些調用會被直接忽略。
2》setTimeout
運行機制:
在指定的毫秒數(shù)后調用函數(shù)或計算表達式。每次函數(shù)執(zhí)行的時候都會創(chuàng)建換一個新的定時器。在前一個定時器代碼執(zhí)行完之前,不會向隊列插入新的定時器代碼,確保不會有任何確實的間隔。并且確保在下一次定時器代碼執(zhí)行之前,至少要等待指定的間隔,避免了連續(xù)的運行。當方法執(zhí)行完成定時器就立即停止(但是定時器還在,只不過沒用了).
缺點:
(1)利用seTimeout實現(xiàn)的動畫在某些低端機上會出現(xiàn)卡頓、抖動的現(xiàn)象。
(2)settimeout的執(zhí)行時間并不是確定的。在js中, settimeout 任務被放進了異步隊列中,只有當主線程上的任務執(zhí)行完以后,才會去檢查該隊列里的任務是否需要開始執(zhí)行,因此 settimeout 的實際執(zhí)行時間一般要比其設定的時間晚一些。
(3)刷新頻率受屏幕分辨率和屏幕尺寸的影響,因此不同設備的屏幕刷新頻率可能會不同,而 settimeout只能設置一個固定的時間間隔,這個時間不一定和屏幕的刷新時間相同。
(4)settimeout的執(zhí)行只是在內存中對圖像屬性進行改變,這個變化必須要等到屏幕下次刷新時才會被更新到屏幕上。如果兩者的步調不一致,就可能會導致中間某一幀的操作被跨越過去,而直接更新下一幀的圖像。
3》requestAnimationFrame
缺點: requestanimationframe 不管理回調函數(shù),即在回調被執(zhí)行前,多次調用帶有同一回調函數(shù)的 requestanimationframe,會導致回調在同一幀中執(zhí)行多次。
解決辦法: 對于這種高頻發(fā)事件,一般的解決方法是使用節(jié)流函數(shù)。但是在這里使用節(jié)流函數(shù)并不能完美解決問題。因為節(jié)流函數(shù)是通過時間管理隊列的,完美的解決方案是通過 requestanimationframe 來管理隊列,其思路就是保證 requestanimationframe 的隊列里,同樣的回調函數(shù)只有一個。
4》與setTimeout和setInterval的區(qū)別
【1】執(zhí)行次數(shù):setInterval執(zhí)行多次,setTimeout、requestAnimationframe執(zhí)行一次
【2】性能:setTimeout會出現(xiàn)丟幀、卡頓現(xiàn)象,setInterval會出現(xiàn)調用丟失情況,requestAnimationframe不會出現(xiàn)這些問題,頁面未激活時不會執(zhí)行動畫,減少了大量cpu消耗
【3】兼容性問題:setInterval,setTimeout在IE瀏覽器中不支持參數(shù)傳遞,能夠在大多數(shù)瀏覽器中正常使用。而requestAnimationframe不兼容IE10以下.
5》requestAnimationFrame補充
除了上文提到的requestAnimationFrame的優(yōu)勢外,requestAnimationFrame還有以下兩個優(yōu)勢:
【1】CPU節(jié)能:使用setTimeout實現(xiàn)的動畫,當頁面被隱藏或最小化時,setTimeout 仍然在后臺執(zhí)行動畫任務,由于此時頁面處于不可見或不可用狀態(tài),刷新動畫是沒有意義的,完全是浪費CPU資源。而requestAnimationFrame則完全不同,當頁面處于未激活的狀態(tài)下,該頁面的屏幕刷新任務也會被系統(tǒng)暫停,因此跟著系統(tǒng)步伐走的requestAnimationFrame也會停止渲染,當頁面被激活時,動畫就從上次停留的地方繼續(xù)執(zhí)行,有效節(jié)省了CPU開銷。
【2】函數(shù)節(jié)流:在高頻率事件(resize,scroll等)中,為了防止在一個刷新間隔內發(fā)生多次函數(shù)執(zhí)行,使用requestAnimationFrame可保證每個刷新間隔內,函數(shù)只被執(zhí)行一次,這樣既能保證流暢性,也能更好的節(jié)省函數(shù)執(zhí)行的開銷。一個刷新間隔內函數(shù)執(zhí)行多次是沒有意義的,因為顯示器每16.7ms刷新一次,多次繪制并不會在屏幕上體現(xiàn)出來。
5.應用場景
【1】監(jiān)聽 scroll 函數(shù) 頁面滾動事件(scroll)的監(jiān)聽函數(shù),就很適合用這個 api,推遲到下一次重新渲染。
【2】大量數(shù)據(jù)渲染 比如對十萬條數(shù)據(jù)進行渲染,主要由以下幾種方法:
(1)使用定時器
(2)使用 requestAnimationFrame
【3】監(jiān)控卡頓方法 :每秒中計算一次網(wǎng)頁的 FPS(畫面每秒傳輸幀數(shù)),獲得一列數(shù)據(jù),然后分析。通俗地解釋就是,通過 requestAnimationFrame API 來定時執(zhí)行一些 JS 代碼,如果瀏覽器卡頓,無法很好地保證渲染的頻率,1s 中 frame 無法達到 60 幀,即可間接地反映瀏覽器的渲染幀率。
總結
到此這篇關于requestAnimationFrame請求動畫幀的文章就介紹到這了,更多相關requestAnimationFrame請求動畫幀內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
npm?install報錯Error:EPERM:operation?not?permitted,rename解決
這篇文章主要給大家介紹了關于npm?install報錯Error:EPERM:operation?not?permitted,rename的解決辦法,文中介紹了可能遇到的多種原因以及解決辦法,需要的朋友可以參考下2024-01-01利用JavaScript實現(xiàn)3D可旋轉粒子矩陣效果
dat.gui.js是一個一個輕量級的圖形用戶界面庫,或者說GUI組件,只有幾十KB,可以用于創(chuàng)建操作控制三維場景的菜單欄等。本文將利用dat.gui.min.js實現(xiàn)3D可旋轉粒子矩陣效果,感興趣的可以了解一下2022-06-06