requestAnimationFrame的作用及使用

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

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

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

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

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

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

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

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

setTimeout的實現(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毫秒為間隔時間改變一次元素的位置以實現(xiàn)元素的動畫效果, 當(dāng)然, 可以通過改變這個間隔時間來微調(diào)動畫效果,可是你永遠(yuǎn)沒有辦法確定最優(yōu)方案,因為它總會和刷新頻率存在交叉。

通過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ù)也會被遞歸的重復(fù)調(diào)用,只是它的調(diào)用和顯示的刷新頻率是一致的,因此動畫效果更加順滑自然,也能找到性能和效果的最佳均衡點,得到最有的解決方案。

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

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

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