requestAnimationFrame的作用及使用

我們平時(shí)實(shí)現(xiàn)JavaScript動(dòng)畫效果時(shí)離不開setInterval或者setTimeout函數(shù),這兩個(gè)函數(shù)本質(zhì)上相同的。

以setInterval為例,他的作用是以相同的時(shí)間間隔執(zhí)行某個(gè)操作,這個(gè)時(shí)間可以自定義,利用這個(gè)特性我們就可以讓然也元素跑起來。

可是這個(gè)函數(shù)有個(gè)毛病,他和顯示器的刷新頻率無法對(duì)應(yīng)。比如說顯示器每100毫秒刷新一次,setInterval函數(shù)設(shè)置的間隔執(zhí)行也是100毫秒,可是我們沒有辦法保證顯示頻率刷新的時(shí)候setInterval的操作正好被執(zhí)行,雖然它們的相對(duì)執(zhí)行時(shí)間相同,可絕對(duì)時(shí)間不一定一致,所以setInterval制作動(dòng)畫的時(shí)候會(huì)出現(xiàn)丟幀和動(dòng)畫效果生硬不連貫等情況。

requestAnimFrame是H5新標(biāo)準(zhǔn)上的東西,在PC瀏覽器上會(huì)出現(xiàn)兼容問題,在移動(dòng)端瀏覽器中可以任意使用。 次函數(shù)會(huì)接受一個(gè)回調(diào)函數(shù),當(dāng)瀏覽器的顯示頻率刷新的時(shí)候,此函數(shù)會(huì)被執(zhí)行。

window.requestAnimationFrame(function( time){
    //顯示頻刷新的時(shí)候被執(zhí)行
});

回調(diào)函數(shù)有一個(gè)參數(shù),是一個(gè)相對(duì)的時(shí)間毫秒值,表示當(dāng)前的刷新時(shí)間。

requestAnimationFrame的回調(diào)函數(shù)并不能被重復(fù)調(diào)用,這點(diǎn)和setInterval不同,它和setTimeout類似,回調(diào)函數(shù)只能被調(diào)用一次,只不過setTimeout可以自定義調(diào)用時(shí)間, requestAnimationFrame的調(diào)用時(shí)間則是跟著系統(tǒng)的刷新頻率走的,所以在實(shí)現(xiàn)動(dòng)畫的時(shí)候,setTimeout比requestAnimationFrame更加靈活, requestAnimationFrame比setTimeout表現(xiàn)效果更加優(yōu)秀。

以在3000毫秒內(nèi)移動(dòng)1500px距離的動(dòng)畫為例

setTimeout的實(shí)現(xiàn)方式

<div id="div" style="width:100px; height:100px; background-color:#000; position: absolute;left:0; top:0;">
    
</div>

<script type="text/javascript">
let divEle = document.getElementById("div");

const distance = 1500;
const timeCount = 3000;

const intervalTime = 10;
let runCount = timeCount / intervalTime;
let moveValue = distance / runCount;

function handler() {
    let left = parseInt(divEle.style.left);
    if(left >= distance) {
        return;
    }
    divEle.style.left = left + moveValue;
    window.setTimeout(handler, intervalTime);
}

window.setTimeout(handler, intervalTime);
</script>

以上代碼通過setTimeout每10毫秒為間隔時(shí)間改變一次元素的位置以實(shí)現(xiàn)元素的動(dòng)畫效果, 當(dāng)然, 可以通過改變這個(gè)間隔時(shí)間來微調(diào)動(dòng)畫效果,可是你永遠(yuǎn)沒有辦法確定最優(yōu)方案,因?yàn)樗倳?huì)和刷新頻率存在交叉。

通過requestAnimationFrame我們可以給出更好的解決方案

<div id="div" style="width:100px; height:100px; background-color:#000; position: absolute;left:0; top:0;">
    
</div>

<script type="text/javascript">

let divEle = document.getElementById("div");

const distance = 1500;
const timeCount = 3000;

function handler( time ) {
    if(time > timeCount) {
        time = timeCount;
    }
    divEle.style.left = time * distance / timeCount;  
    window.requestAnimationFrame( handler );
}

 window.requestAnimationFrame( handler );
</script>

如果setTimeout,handler函數(shù)也會(huì)被遞歸的重復(fù)調(diào)用,只是它的調(diào)用和顯示的刷新頻率是一致的,因此動(dòng)畫效果更加順滑自然,也能找到性能和效果的最佳均衡點(diǎn),得到最有的解決方案。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容