簡介
以往常常使用 setTimeout 以及 setInterval 方法來制作 JavaScript 動畫,但是這種方式制作的動畫經(jīng)常會由于計(jì)時器的特性而帶來一些問題截碴。簡單地說一下俏险,計(jì)時器動畫有以下幾個問題上沐。
- 間隔時間不精確整吆,可能被阻塞疹鳄。計(jì)時器的間隔指的是將回調(diào)函數(shù)推入任務(wù)隊(duì)列的間隔時間赋朦,任務(wù)隊(duì)列中的任務(wù)只有在主線程任務(wù)執(zhí)行完畢后才會被執(zhí)行篓冲。
- 計(jì)時器動畫的間隔時間如果設(shè)定過短就會出現(xiàn)過度渲染占用大量資源,如果設(shè)定過長就會影響動畫的流暢度宠哄。只能夠估計(jì)合適的時間間隔壹将。
- 多數(shù)瀏覽器對于計(jì)時器動畫沒有優(yōu)化。
使用 requestAnimationFrame 方法來定義動畫就不會出現(xiàn)以上這些問題毛嫉。
- requestAnimationFrame 動畫的幀數(shù)是由系統(tǒng)根據(jù)當(dāng)前頁面是否可見诽俯,CPU 的占用情況等等來決定的,可以最大化地利用系統(tǒng)性能承粤。
- 瀏覽器對 requestAnimationFrame 動畫進(jìn)行了優(yōu)化暴区。
使用
requestAnimationFrame() 方法接收一個參數(shù)闯团,即要執(zhí)行的回調(diào)函數(shù)。這個回調(diào)函數(shù)會默認(rèn)地傳入一個參數(shù)仙粱,即從打開頁面到回調(diào)函數(shù)被觸發(fā)時的時間長度房交,單位為毫秒,精確度為10微秒伐割。這個方法返回一個唯一的 handle 值候味,handle值 作為這個回調(diào)函數(shù)唯一的標(biāo)識符,可以通過將這個標(biāo)識符傳給 cancleAnimationFrame() 方法來取消這個回調(diào)函數(shù)隔心。
原理
requestAnimationFrame() 方法接受一個回調(diào)函數(shù)白群,同時隨機(jī)生成一個唯一的 handle 值作為標(biāo)識符∮不簦回調(diào)函數(shù)和 handle 值共同組成一個元組 <handle, callback>帜慢,然后將這個元組推入動畫幀請求回調(diào)函數(shù)隊(duì)列中。
當(dāng)頁面可見時唯卖,如果動畫幀請求回調(diào)函數(shù)隊(duì)列中有元組粱玲,那么瀏覽器就會清空隊(duì)列并且執(zhí)行這些回調(diào)函數(shù)。
另外耐床,每一個元組有一個 canceled 標(biāo)識符,如果為 false楔脯,那么這個回調(diào)函數(shù)就不會在清空隊(duì)列后被執(zhí)行撩轰。cancleAnimationFrame() 方法的原理就是將這個標(biāo)識符設(shè)置為 false。
示例
var startTime;
function sayHi(time){
if(!startTime){
startTime = time;
}
time -= startTime;
console.log("Hi");
if (time <= 2000) {
requestAnimationFrame(sayHi);
}
}
requestAnimationFrame(sayHi);