requestAnimationFrame
來(lái)看一個(gè)小例子
<body>
<div id="box"></div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
function run(){
box.innerHTML = new Date().getTime();
setTimeout(run, 16);
}
setTimeout(run, 16);
</script>
這個(gè)例子當(dāng)中, 我們通過(guò)setTimeout讓run函數(shù)每秒執(zhí)行60次.
想要按照瀏覽器的刷新頻率來(lái)執(zhí)行函數(shù), 其實(shí)不需要這么麻煩.
另外, 如果瀏覽器的刷新頻率不是60, 甚至低于60, 那么我們的動(dòng)畫(huà)就可能出現(xiàn)掉幀情況.
啥叫掉幀?
一般情況下, 瀏覽器的幀率跟屏幕幀率一致, 基本都是60, 也就是16ms左右會(huì)刷新一次
如果, 你的定時(shí)器時(shí)間過(guò)短, 就會(huì)出現(xiàn)上圖的現(xiàn)象.
在瀏覽器兩次刷新畫(huà)面中間, 定時(shí)器函數(shù)執(zhí)行了2次
而這2次操作都是在內(nèi)存完成的動(dòng)作, 瀏覽器只有刷新才能看到效果
也就是說(shuō), 用戶(hù)本該看到的兩幀畫(huà)面, 丟了一幀.
畫(huà)面會(huì)顯得不流暢, 甚至一定程度上出現(xiàn) "卡頓"
這就是俗稱(chēng)的掉幀現(xiàn)象.
解決這個(gè)問(wèn)題, 直觀(guān)的辦法就是把延遲時(shí)間寫(xiě)的長(zhǎng)一點(diǎn).
這里我們引入更簡(jiǎn)單的方法
<body>
<div id="box"></div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
function run(){
box.innerHTML = new Date().getTime();
requestAnimationFrame(run);
}
requestAnimationFrame(run);
</script>
requestAnimationFrame 類(lèi)似于 setTimeout, 只不過(guò)它不需要設(shè)定延遲時(shí)間
時(shí)間會(huì)根據(jù)瀏覽器的幀率自動(dòng)調(diào)節(jié). 也就是在瀏覽器下一次刷新前調(diào)用這個(gè)函數(shù)
每次刷新前, 調(diào)用1次函數(shù), 確保函數(shù)的執(zhí)行頻率跟刷新頻率一致.
由于是每一幀畫(huà)面執(zhí)行1次函數(shù), 因此requestAnimationFrame又叫 "幀動(dòng)畫(huà)" 函數(shù),它會(huì)帶來(lái)兩個(gè)好處:
1. 避免了計(jì)算 1000/60 ≈ 16, 瀏覽器會(huì)自動(dòng)處理
2. 當(dāng)標(biāo)簽頁(yè)運(yùn)行在后臺(tái)的時(shí)候, 它會(huì)自動(dòng)暫停運(yùn)行以節(jié)省CPU資源
經(jīng)過(guò)我的實(shí)際測(cè)試, chrome\firefox\360\ie11, 幀率都是60
也就是說(shuō), 除非你把延遲時(shí)間 設(shè)定的 小于 16, 才有可能在理論上出現(xiàn)掉幀
又由于setTimeout是異步任務(wù), 所以實(shí)際當(dāng)中的時(shí)間間隔往往是大于實(shí)際值的
因此, 掉幀的情況是很難發(fā)生的.
所以, requestAnimationFrame方法的主要好處來(lái)源于第2條.
更多關(guān)于web前端培訓(xùn)的問(wèn)題,歡迎咨詢(xún)千鋒教育在線(xiàn)名師,如果想要了解我們的師資、課程、項(xiàng)目實(shí)操的話(huà)可以點(diǎn)擊咨詢(xún)課程顧問(wèn),獲取試聽(tīng)資格來(lái)試聽(tīng)我們的課程,在線(xiàn)零距離接觸千鋒教育大咖名師,讓你輕松從入門(mén)到精通。