首先屡贺,MDN的定義是:
window.requestAnimationFrame() 告訴瀏覽器——你希望執(zhí)行一個(gè)動(dòng)畫(huà)侮腹,并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動(dòng)畫(huà)缓苛。該方法需要傳入一個(gè)回調(diào)函數(shù)作為參數(shù)嘴纺,該回調(diào)函數(shù)會(huì)在瀏覽器下一次重繪之前執(zhí)行
注意:若你想在瀏覽器下次重繪之前繼續(xù)更新下一幀動(dòng)畫(huà)几睛,那么回調(diào)函數(shù)自身必須再次調(diào)用window.requestAnimationFrame()
結(jié)論:
當(dāng)你準(zhǔn)備更新動(dòng)畫(huà)時(shí)你應(yīng)該調(diào)用此方法房轿。這將使瀏覽器在下一次重繪之前調(diào)用你傳入給該方法的動(dòng)畫(huà)函數(shù)(即你的回調(diào)函數(shù))∷回調(diào)函數(shù)執(zhí)行次數(shù)通常是每秒60次囱持,但在大多數(shù)遵循W3C建議的瀏覽器中,回調(diào)函數(shù)執(zhí)行次數(shù)通常與瀏覽器屏幕刷新次數(shù)相匹配必峰。為了提高性能和電池壽命洪唐,因此在大多數(shù)瀏覽器里,當(dāng)
requestAnimationFrame()
運(yùn)行在后臺(tái)標(biāo)簽頁(yè)或者隱藏的<iframe>
里時(shí)吼蚁,requestAnimationFrame()
會(huì)被暫停調(diào)用以提升性能和電池壽命凭需。
關(guān)于其他:
瀏覽器渲染
- 在地址欄中輸入U(xiǎn)RL后,當(dāng)前的瀏覽器進(jìn)程中的UI線程會(huì)啟動(dòng)一個(gè)網(wǎng)絡(luò)請(qǐng)求線程
- 網(wǎng)絡(luò)請(qǐng)求線程請(qǐng)求到的數(shù)據(jù)會(huì)經(jīng)過(guò)安全驗(yàn)證肝匆,確認(rèn)安全后粒蜈,UI線程會(huì)開(kāi)啟一個(gè)渲染器進(jìn)程
- 渲染器進(jìn)程中的主線程負(fù)責(zé)html解析和js的執(zhí)行。
- 具體的解析過(guò)程就不贅述了旗国,解析出來(lái)
Layout Tree
后枯怖,為了顯示到屏幕上會(huì)進(jìn)行柵格化。這會(huì)在新開(kāi)辟的合成器線程中執(zhí)行 - 合成器線程返回的合成器幀會(huì)被回傳給瀏覽器進(jìn)程能曾,最后顯示到屏幕上度硝。
以上是大致流程,有很多細(xì)節(jié)沒(méi)講清楚寿冕,比如合成器線程如何柵格化蕊程、html如何被解析,這些有機(jī)會(huì)放到以后解釋
那么requestAnimationFrame()
發(fā)生在哪個(gè)階段驼唱?答案是渲染器進(jìn)程的主線程中藻茂,因?yàn)樵谠撝骶€程中不只會(huì)解析html還會(huì)執(zhí)行js
動(dòng)畫(huà)卡頓原因
以60幀動(dòng)畫(huà)為例
每一幀約為16ms,在一幀中,當(dāng)解析渲染html的用時(shí)小于16ms時(shí)辨赐,一幀中主線程會(huì)有空余時(shí)間优俘,這時(shí),js會(huì)被推入主線程執(zhí)行掀序。問(wèn)題在于js如果執(zhí)行時(shí)間太長(zhǎng)帆焕,比如20ms,會(huì)導(dǎo)致js不僅占滿(mǎn)了當(dāng)前幀的空余時(shí)間森枪,甚至把下一幀原本用來(lái)渲染的時(shí)間也占用了视搏,這會(huì)造成渲染的阻塞,顯示到頁(yè)面上县袱,就是動(dòng)畫(huà)可能會(huì)出現(xiàn)卡頓浑娜,掉幀
requestAnimationFrame()
功效
往該函數(shù)中傳入1個(gè)回調(diào)函數(shù),把原先的js代碼塞到回調(diào)函數(shù)中式散,他會(huì)告訴瀏覽器筋遭,我有代碼必須在下一幀來(lái)臨前就執(zhí)行,這些代碼會(huì)在下一次渲染前執(zhí)行完畢暴拄。通常漓滔,我們這個(gè)回調(diào)函數(shù)里面做一些動(dòng)畫(huà)的更新,那么它可以保證下一次渲染前乖篷,dom已經(jīng)通過(guò)代碼更新了响驴,可以被渲染,這也就防止了頁(yè)面的阻塞