如何計算瀏覽器頁面的幀數 FPS?

前端西瓜哥 發佈 2022-12-12T01:58:49.191926+00:00

大家好,我是前端西瓜哥。今天說說如何計算瀏覽器頁面的幀數。我們需要用到 requestAnimationFrame 方法。requestAnimationFramerequestAnimationFrame 方法接受一個回調函數,並會在 瀏覽器下一次重渲染前調用 這個回調函數。

大家好,我是前端西瓜哥。今天說說如何計算瀏覽器頁面的幀數。

我們需要用到 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。

我是前端西瓜哥,歡迎關注我,學習更多前端知識。

關鍵字: