写作背景
今日逛 B 站,发现在弹幕大量涌出来的时候,做了掉帧监测,然后减少掉一些弹幕的出现。那么笔者对 JS 怎么做掉帧监测到的感兴趣。
查了一下方法,还真有一个叫 Frame Timing API 的东西,还是草案,也不是 W3C 标准的,截至 Chrome 80 仍旧没有被支持的迹象。
那么该怎么办?
计算分析
若你常常玩游戏,看视频,就知道有一个 FPS 的概念,举个例子若是 60 FPS,代表一秒钟有 60 桢,也就是渲染 60 个画面,而人的眼球视觉能觉得动画连贯的最低帧数要求是 24 帧每秒。
也就是 FPS 低于 24 时,你会感到卡顿,那么问题化作如何计算 FPS?
- 设置一个定时器,定时器间隔 16.67ms 执行一段代码计算。
- 计算的内容是与上一次执行此定时器的时间间隔(ms)
- 当前时刻的 FPS = 1000ms / 时间间隔(ms)
- 当前时刻的 FPS 小于 24,你就知道页面有卡顿。
代码
var lastFrameTime = performance.now();
var checkFPS = function() {
times += 1;
var now = performance.now();
if (now === lastFrameTime) {
window.requestAnimationFrame(checkFPS);
return;
}
var fps = Math.round(1000 / (now - lastFrameTime));
// 那么你知道在上一次执行到本次执行之间,页面有卡顿
if (fps < 24) {
console.log('fps lower', fps);
}
lastFrameTime = now;
window.requestAnimationFrame(checkFPS);
}
代码很简单,注意上文的代码定时器不用 setTimeout 而用 window.requestAnimationFrame,是因为 setTimeout 受事件循环影响因素太大。 MDN-window.requestAnimationFrame 文档里所说
浏览器重绘频率一般会和显示器的刷新率保持同步。大多数浏览器采取 W3C 规范的建议,浏览器的渲染页面的标准帧率也为 60FPS(frames/ per second)
在 B 站控制台里执行,发现还是触发的停频繁的
但我在看视频的时候并没有感到很卡,所以想让上面的代码更加可实用,还得加一个因素,就是连续若干次 FPS 低于 24。参考了一下网上其他人的意见,是出现连续 3 次低于 FPS 20 的,就可以判定位卡。
这个改进,留个坑给以后补吧。