簡介
以往常常使用 setTimeout 以及 setInterval 方法來制作 JavaScript 動畫,但是這種方式制作的動畫經常會由于計時器的特性而帶來一些問題。簡單地說一下,計時器動畫有以下幾個問題。
- 間隔時間不精確,可能被阻塞。計時器的間隔指的是將回調函數推入任務隊列的間隔時間,任務隊列中的任務只有在主線程任務執行完畢后才會被執行。
- 計時器動畫的間隔時間如果設定過短就會出現過度渲染占用大量資源,如果設定過長就會影響動畫的流暢度。只能夠估計合適的時間間隔。
- 多數瀏覽器對于計時器動畫沒有優化。
使用 requestAnimationFrame 方法來定義動畫就不會出現以上這些問題。
- requestAnimationFrame 動畫的幀數是由系統根據當前頁面是否可見,CPU 的占用情況等等來決定的,可以最大化地利用系統性能。
- 瀏覽器對 requestAnimationFrame 動畫進行了優化。
使用
requestAnimationFrame() 方法接收一個參數,即要執行的回調函數。這個回調函數會默認地傳入一個參數,即從打開頁面到回調函數被觸發時的時間長度,單位為毫秒,精確度為10微秒。這個方法返回一個唯一的 handle 值,handle值 作為這個回調函數唯一的標識符,可以通過將這個標識符傳給 cancleAnimationFrame() 方法來取消這個回調函數。
原理
requestAnimationFrame() 方法接受一個回調函數,同時隨機生成一個唯一的 handle 值作為標識符。回調函數和 handle 值共同組成一個元組 <handle, callback>,然后將這個元組推入動畫幀請求回調函數隊列中。
當頁面可見時,如果動畫幀請求回調函數隊列中有元組,那么瀏覽器就會清空隊列并且執行這些回調函數。
另外,每一個元組有一個 canceled 標識符,如果為 false,那么這個回調函數就不會在清空隊列后被執行。cancleAnimationFrame() 方法的原理就是將這個標識符設置為 false。
示例
var startTime;
function sayHi(time){
if(!startTime){
startTime = time;
}
time -= startTime;
console.log("Hi");
if (time <= 2000) {
requestAnimationFrame(sayHi);
}
}
requestAnimationFrame(sayHi);