RequestAnimationFrame知多少?
在web應(yīng)用中,實(shí)現(xiàn)動(dòng)畫效果的方法比較多,例如js中可以通過定時(shí)器setTimeout來實(shí)現(xiàn);CSS3可以通過transition和animation來實(shí)現(xiàn);html5中通過Canvas來實(shí)現(xiàn)。除此之外,html5還提供一個(gè)專門用于請(qǐng)求動(dòng)畫的API,即requestAnimationFrame(請(qǐng)求動(dòng)畫幀)。
?屏幕繪制頻率:
即圖像在屏幕上更新的速度,即屏幕上圖像每秒出現(xiàn)的次數(shù),一般這個(gè)頻率是60HZ,所以一幅畫面的刷新頻率大約是16.7ms。大多數(shù)瀏覽器都會(huì)對(duì)重繪操作加以限制,不超過顯示器的重繪頻率,以為即使超過那個(gè)頻率用戶的體驗(yàn)也不會(huì)提升。
?
CSS動(dòng)畫原理
動(dòng)畫的本質(zhì)就是讓人眼看到圖像被繪制而引起變化的視覺效果,這個(gè)變化要連貫、平滑的方式進(jìn)行過渡。因?yàn)殡娔X屏幕以每秒60次的頻率繪制,繪制頻率很高所以感覺不到它在繪制。
js中使用setTimeout實(shí)現(xiàn)動(dòng)畫在某些低端機(jī)上會(huì)出現(xiàn)卡頓、抖動(dòng)的現(xiàn)象,主要有兩個(gè)原因:
(1)setTimeout的執(zhí)行時(shí)間并不是確定的。在js中setTimeout任務(wù)被放入異步隊(duì)列中,只有當(dāng)主線程上的任務(wù)執(zhí)行完之后,才會(huì)去檢查異步任務(wù)是否需要開始執(zhí)行,所以setTimeout的執(zhí)行時(shí)間一般比設(shè)定的晚一些。
(2)刷新頻率受屏幕分辨率和屏幕尺寸影響,不同設(shè)備的屏幕繪制頻率可能會(huì)不同,而setTimeout只能設(shè)置一個(gè)固定的時(shí)間間隔,這個(gè)時(shí)間不一定和屏幕的刷新時(shí)間相同。
以上兩種情況都會(huì)導(dǎo)致setTimeout的執(zhí)行步調(diào)和屏幕的刷新步調(diào)不一致,從而引起丟幀現(xiàn)象。所以為什么步調(diào)不一致會(huì)出現(xiàn)丟幀呢?
首先setTimeout的執(zhí)行只是在內(nèi)存中對(duì)元素的屬性進(jìn)行改變,這個(gè)變化必須要等到屏幕下次繪制時(shí)才會(huì)被更新到屏幕上。如果步調(diào)不一致會(huì)導(dǎo)致中間某些幀的操作直接被跨越過去,而直接更新下一幀。
假設(shè)屏幕每隔16.7ms刷新一次,而setTimeout 每隔10ms設(shè)置圖像向左移動(dòng)1px, 就會(huì)出現(xiàn)如下繪制過程(表格)
從上面的繪制過程中可以看出,屏幕沒有更新 left=2px 的那一幀畫面,元素直接從left=1px 的位置跳到了 left=3px 的的位置,這就是丟幀現(xiàn)象,這種現(xiàn)象就會(huì)引起動(dòng)畫卡頓。
?
requestAnimationFrame(rAF)
與setTimeout相比,rAF的最大優(yōu)勢(shì)是由系統(tǒng)來決定回調(diào)函數(shù)的執(zhí)行時(shí)機(jī)。具體來講就是,系統(tǒng)每次繪制之前都會(huì)主動(dòng)調(diào)用rAF中的回調(diào)函數(shù)。所以rAF的執(zhí)行頻率是跟著系統(tǒng)的繪制頻率走的,他能保證回調(diào)函數(shù)在屏幕每一次的繪制間隔中只被執(zhí)行一次,這樣就不會(huì)出現(xiàn)丟幀現(xiàn)象和動(dòng)畫卡頓。
?
requestAnimationFrame()方法接收一個(gè)參數(shù),即在繪制屏幕前調(diào)用的一個(gè)函數(shù),這個(gè)函數(shù)負(fù)責(zé)改變下一次繪制的DOM樣式。
function updateProcess(){var div=document.getElementById('status');div.style.width=(parseInt(div.style.width)+5)+'px';if(div.style.width!="300px"){window.requestAnimationFrame(updateProcess);} } window.requestAnimationFrame(updateProcess);rAF還有兩個(gè)優(yōu)勢(shì):
(1)CPU節(jié)能:使用setTimeout實(shí)現(xiàn)的動(dòng)畫,當(dāng)頁(yè)面被隱藏或最小化時(shí),setTimeout仍然在后臺(tái)執(zhí)行動(dòng)畫任務(wù),由于此時(shí)頁(yè)面處于不可見或不可用的狀態(tài),刷新動(dòng)畫是沒有意義的,還浪費(fèi)CPU資源。而rAF不同,當(dāng)頁(yè)面處于未激活的狀態(tài)下,該頁(yè)面的屏幕繪制任務(wù)也被系統(tǒng)暫停,因此跟著系統(tǒng)步伐的rAF也停止渲染,當(dāng)頁(yè)面被激活時(shí),動(dòng)畫就從上次停留的地方繼續(xù)執(zhí)行,有效節(jié)約了CPU開銷。
(2)函數(shù)節(jié)流:在高頻率事件(resize、scroll等)這種,為了防止在一個(gè)刷新間隔內(nèi)發(fā)生多次函數(shù)執(zhí)行,使用rAF可保證每個(gè)繪制間隔內(nèi)函數(shù)只被執(zhí)行一次,這樣既能保證流暢性,也能更好的節(jié)省函數(shù)執(zhí)行的開銷。
?
轉(zhuǎn)載于:https://www.cnblogs.com/xiaoan0705/p/11212149.html
總結(jié)
以上是生活随笔為你收集整理的RequestAnimationFrame知多少?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Luogu2791 幼儿园篮球题【斯特林
- 下一篇: 常数优化的一些技巧