在講解這個API之前,我們先來了解一些基礎知識:
屏幕刷新頻率:屏幕每秒出現圖像的次數。普通筆記本爲60Hz。1000 / 60 ≈16.67 ,所以計算機每16.7ms刷新一次,由於人眼的視覺停留,所以看起來是流暢的移動。
setTimeout:通過設定間隔時間來不斷改變圖像位置,達到動畫效果。但是容易出現卡頓、抖動的現象;原因是:1、settimeout任務被放入異步隊列,只有當主線程任務執行完後纔會執行隊列中的任務,因此實際執行時間總是比設定時間要晚。2、settimeout的固定時間間隔不一定與屏幕刷新時間相同,會引起丟幀。
在知道了上述知識後,我們就開始今天的主題:
window.requestAnimationFrame(callback):
由系統決定回調函數的執行時機。60Hz的刷新頻率,那麼每次刷新的間隔中會執行一次回調函數,不會引起丟幀,不會卡頓。
下面我們用定時器來實現一個動畫,
let dis = 0;
let timer = null;
timer = setInterval(function(){
clearInterval(timer);
div.style.left = dis++;
if(dis>=50) clearInterval(timer)
},16.7)
我改造成requestAnimationFrame版本:
let dis =0;
function animation(){
requestAnimationFrame(function(){
div.style.left = dis++;
if(disx<50) animation();
})
}
animation();
requestAnimationFrame 比起 setTimeout、setInterval的優勢主要有三點:
- requestAnimationFrame 會把每一幀中的所有DOM操作集中起來,在一次重繪或迴流中就完成,並且重繪或迴流的時間間隔緊緊跟隨瀏覽器的刷新頻率,一般來說,這個頻率爲每秒60幀。
- 在隱藏或不可見的元素中,requestAnimationFrame將不會進行重繪或迴流,這當然就意味着更少的的cpu,gpu和內存使用量。
-
在高頻率事件(resize,scroll等)中,爲了防止在一個刷新間隔內發生多次函數執行,使用requestAnimationFrame可保證每個刷新間隔內,函數只被執行一次,這樣既能保證流暢性,也能更好的節省函數執行的開銷。