眼睛的另壹個重要特是視覺惰,即光象壹旦在視網膜上形成,視覺將會對這個光象的感覺維持壹個有限的時間,這種生理現象叫做 視覺暫留 。對於中等亮度的光刺激,視覺暫留時間約為 50ms 至 200ms 。當我們看屏幕的時候,雖然妳什麽也沒做,但是屏幕還是以特定的頻率在不停刷新,只是這個刷新過程我們肉眼識別到他的細微變化,這就是我們接下來要說的 屏幕刷新頻率
我們日常的顯示器,壹般頻率在 60Hz 左右,意味著我們的屏幕每 1 秒需要刷新 60 次,也就是說每 1000ms 需要更新 60 次的屏幕圖像,那麽我們由此可以得出,屏幕圖像更新壹次所需要的時間間隔也就是 16.7ms(1000/60≈16.7) 。
由於人的眼睛具有 視覺暫留效應 ,且暫留時間為 50ms 至 200ms ,也就是說人在看屏幕的時候,還沒等到妳的大腦印象消失,電腦屏幕就已經更新了,所以這個間隔讓妳感覺不到變化。
那麽屏幕刷新頻率是不是越大越好?我們可以大膽假設壹下,假如我有三個顯示器,刷新頻率分別為 1Hz 、 60Hz 、 200Hz 、那麽對應的更新周期時間分別為 1000ms 、 16.7ms 、 5ms 。 也就是頻率越大,圖像更新的間隔就越短,我們看到的畫面就會越穩定, 當達到壹秒更新壹次的時候,這個時候我們就能夠感覺到明顯的屏幕閃爍,帶來視覺疲勞。
setTimeout 說白了就是個延時計時器,通過設置固定的時間間隔,從而時間壹到,執行相應的回調方法。這個過程不會考慮屏幕刷新頻率,換句話講,它的時間是寫死的。那麽為什麽會存在丟幀現象發生,通俗來說就是為什麽使用 setTimeout 我會感覺到卡頓,畫面不穩定。
1. setTimeout 執行的時間與屏幕的刷新頻率不壹致會導致丟幀現象。我們不考慮異步問題,假設我們現在的屏幕設備是 60Hz 的刷新頻率。那麽我們圖像的更新周期也就是 16.7ms ,我現在的動畫要求是每 10ms 往下偏移 1px ,那麽這個丟幀現象是如何產生的?這裏我通過壹張圖來解釋壹下。
所以根據分析結果以及實驗效果,如果 setTimeout 執行的順序與屏幕的刷新頻率不壹致,會造成丟幀現象,從而視覺上帶給我們的就是不流暢 。
2.由於 JavaScript 屬於 單線程 ,而 setTimeout 任務會被放入異步隊列,通俗來講就是它的執行得等壹等,具體等什麽,不知道,就是想再等等。只有主線程的任務執行完畢之後,才會輪到它去執行,也就是說我雖然設置 setTimeout 16.7ms 間隔去執行動畫屬性改變,但是實際運行的時間可能會有所延遲。這個延遲可能會導致執行的時間與屏幕刷新的時間串掉,造成丟幀。
官方解釋 : window.requestAnimationFrame() 告訴瀏覽器——妳希望執行壹個動畫,並且要求瀏覽器在下次重繪之前調用指定的回調函數更新動畫。該方法需要傳入壹個回調函數作為參數,該回調函數會在瀏覽器下壹次重繪之前執行。也就是說 requestAnimationFrame 它不需要妳去手動設置執行間隔時間,它是跟隨系統的屏幕刷新頻率走的,如果屏幕刷新頻率是 60Hz ,那麽它的執行間隔就是 16.7ms(1000/60≈16.7) ,如果屏幕刷新頻率是 100Hz ,那麽它的執行間隔就是 10ms(1000/100=10) ,這樣就能夠保證它的執行與屏幕的刷新頻率保持壹致,從而避免丟幀現象。
為了提高性能和電池壽命,因此在大多數瀏覽器裏,當 requestAnimationFrame() 運行在後臺標簽頁或者隱藏的 <iframe> 裏時, requestAnimationFrame() 會被暫停調用以提升性能和電池壽命。
源地址: /darius/requestAnimationFrame