requestAnimationFrame 是瀏覽器用於定時循環操作的一個接口,類似於setTimeout,主要用途是按幀對網頁進行重繪。
設置這個API的目的是爲了讓各種網頁動畫效果(DOM動畫、Canvas動畫、SVG動畫、WebGL動畫)能夠有一個統一的刷新機制,從而節省系統資源,提高系統性能,改善視覺效果。代碼中使用這個API,就是告訴瀏覽器希望執行一個動畫,讓瀏覽器在下一個動畫幀安排一次網頁重繪。
requestAnimationFrame的優勢,在於充分利用顯示器的刷新機制,比較節省系統資源。顯示器有固定的刷新頻率(60Hz或75Hz),也就是說,每秒最多隻能重繪60次或75次,requestAnimationFrame的基本思想就是與這個刷新頻率保持同步,利用這個刷新頻率進行頁面重繪。此外,使用這個API,一旦頁面不處於瀏覽器的當前標籤,就會自動停止刷新。這就節省了CPU、GPU和電力。
不過有一點需要注意,requestAnimationFrame是在主線程上完成。這意味着,如果主線程非常繁忙,requestAnimationFrame的動畫效果會大打折扣。
requestAnimationFrame使用一個回調函數作爲參數。這個回調函數會在瀏覽器重繪之前調用。
requestID = window.requestAnimationFrame(callback);
目前,主要瀏覽器Firefox 23 / IE 10 / Chrome / Safari)都支持這個方法。可以用下面的方法,檢查瀏覽器是否支持這個API。如果不支持,則自行模擬部署該方法。
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
/*按照1秒鐘60次(大約每16.7毫秒一次),來模擬requestAnimationFrame。*/
window.setTimeout(callback, 1000 / 60);
};
})();
使用requestAnimationFrame的時候,只需反覆調用它即可。
(function repeatOften() {
console.log('持續輸出')
requestAnimationFrame(repeatOften);
})()
cancelAnimationFrame方法用於取消重繪
window.cancelAnimationFrame(requestID);
//它的參數是requestAnimationFrame返回的一個代表任務ID的整數值。
//持續在body元素下添加div元素,直到用戶點擊stop按鈕爲止。
var globalID;
function repeatOften() {
var div = document.createElement("div");
div.innerHTML = '創建div';
document.body.appendChild(div);
globalID = requestAnimationFrame(repeatOften);
}
document.getElementById('start').addEventListener('click',function(){
globalID = requestAnimationFrame(repeatOften);
})
document.getElementById('stop').addEventListener('click',function(){
cancelAnimationFrame(globalID);
})
實例
<div id="anim">點擊運行動畫</div>
var elem = document.getElementById("anim");
var startTime = undefined;
let margin = 0;
let isContinue = true;
function render() {
margin===200?isContinue=false:margin===0?isContinue=true:false;
isContinue?elem.style.left = `${margin++}px`:elem.style.left = `${margin--}px`;
}
elem.addEventListener('click',function animloop(){
render();
requestAnimFrame(animloop);
})