大家好,我是前端西瓜哥。今天說說如何計算瀏覽器頁面的幀數。
我們需要用到 requestAnimationFrame 方法。
requestAnimationFrame
requestAnimationFrame 方法接受一個回調函數,並會在 瀏覽器下一次重渲染前調用 這個回調函數。
此外,我們通常 raf 來代表冗長的 requestAnimationFrame。
const id = window.requestAnimationFrame((timestamp) => {
// ...
})
回調函數會拿到一個高精度的時間點,稱為 DOMHighResTimeStamp,表示執行回調函數的時刻。單位是 ms,有小數位,精度較高。Performance.now() 的返回值也是 DOMHighResTimeStamp。
需要注意的是這個時間點並不是當前時間的時間戳,而是從應用啟動後進過的時間。
另外,可以通過 cancelAnimationFrame 方法取消,需要提供 raf 返回的 id:
cancelAnimationFrame(id);
實時顯示 FPS
FPS,是 frames per second 的縮寫,也就是一秒渲染了多少幀的畫面。對於瀏覽器來說,通常 fps 為 60。
FPS = 一秒的幀數 / 1s
配合 raf 會在每次重繪前執行,我們可以計算在 1 秒內,統計調用 raf 的次數 count。當時間間隔超過 1 秒後,就讀取這個 count,然後重置 count 和間隔開始時間。
實現如下:
let count = 0;
let prevTimestamp;
function showFPS(fps) {
// 這裡設置如何將 fps 數值輸出
// 比如你可以將其更新到某個 DOM 元素上
console.log(fps);
}
function loop(timestamp) {
if (prevTimestamp) {
count++;
// 間隔超過 1s,將之前計算的 count 輸出
if (timestamp - prevTimestamp >= 1000) {
showFPS(count);
prevTimestamp = timestamp;
count = 0;
}
} else {
prevTimestamp = timestamp;
}
window.requestAnimationFrame(loop);
}
window.requestAnimationFrame(loop);
理論上,我們還可以直接用 1 / timestamp * 1000 得到幾毫秒內的 FPS。
但沒有太大意義,因為過於微觀,可能突然在某個瞬間卡頓,但很快又恢復正常,這個微小的變化容易忽略,如果體現在 1 s 中則更容易觀測些。且頻繁地將 FPS 值列印出來,其本身也會導致性能的下降,不利於觀測。
結尾
利用 requestAnimationFrame 會在頁面渲染前執行的特性,我們可以去計算頁面的 FPS。
我是前端西瓜哥,歡迎關注我,學習更多前端知識。