网站添加FPS检测的功能

显示效果如下

image-20240909144700097

FPS分级:

  • fps <= 30 – > 电竞级帧率😓
  • fps <= 60 – > 有点难受😨
  • fps <= 90 – >不太流畅😥
  • fps <= 120 –> 还不错哦😀
  • fps > 120 –> 十分流畅😆

操作步骤

  1. 新建js文件G:\Blog\source\js\fps.js,写入如下代码(最初版)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
if (window.localStorage.getItem("fpson") == undefined || window.localStorage.getItem("fpson") == "1") {
var rAF = function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
}();
var frame = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();
var loop = function () {
var now = Date.now();
var fs = (now - lastFameTime);
var fps = Math.round(1000 / fs);

lastFameTime = now;
// 不置 0,在动画的开头及结尾记录此值的差值算出 FPS
allFrameCount++;
frame++;

if (now > 1000 + lastTime) {
var fps = Math.round((frame * 1000) / (now - lastTime));
if (fps <= 5) {
var kd = `<span style="color:#39c5bb">卡成ppt😭</span>`
} else if (fps <= 15) {
var kd = `<span style="color:#39c5bb">电竞级帧率😓</span>`
} else if (fps <= 25) {
var kd = `<span style="color:#39c5bb">有点难受😨</span>`
} else if (fps < 35) {
var kd = `<span style="color:#39c5bb">不太流畅😥</span>`
} else if (fps <= 45) {
var kd = `<span style="color:#39c5bb">还不错哦😀</span>`
} else {
var kd = `<span style="color:#39c5bb">十分流畅😆</span>`
}
document.getElementById("fps").innerHTML = `FPS:${fps} ${kd}`;
frame = 0;
lastTime = now;
};

rAF(loop);
}

loop();
} else {
document.getElementById("fps").style = "display:none!important"
}
  1. 在自定义样式G:\Blog\source\css\custom.css添加如下代码,可以自定义位置,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 帧率检测 */
#fps {
position: fixed;
/* 指定位置 left是左 right是右 位置大小自己调*/
left: 10px;
bottom: 10px;
z-index: 1919810;
}
/* 黑夜模式和白天模式的背景颜色、透明度设置 */
[data-theme="light"] #fps {
background-color: rgba(255, 255, 255, 0.85);
backdrop-filter: var(--backdrop-filter);
padding: 5px;
/* 设置图标圆角*/
border-radius: 8px;
}
[data-theme="dark"] #fps {
background-color: rgba(0, 0, 0, 0.72);
backdrop-filter: var(--backdrop-filter);
padding: 5px;
border-radius: 8px;
}
  1. 在主题配置文件G:\Blog\_config.butterfly.yml添加如下代码

    1
    2
    3
    4
    5
    inject: 
    head:
    + - <span id="fps"></span> # 帧率检测
    bottom:
    + - <script async src="/js/fps.js"></script> # 帧率检测
  2. 重新部署,最好先hexo clean

不完美之处

如果只有一块屏幕或者使用手机,都可以正确显示停留网站时的FPS,但是如果使用双屏两块屏幕刷新率不一致,那么上面的脚本只能显示主屏幕的刷新率(一般是刷新率最高的那一块屏),如果经常切换浏览器的显示屏幕,例如把浏览器从屏幕1切换到屏幕2,那么脚本显示的还是屏幕1的FPS,无法实时显示屏幕2的FPS

尝试修改js代码(失败)

修改过几版,但是每一版都无法实现实时显示FPS

版本1

监听屏幕的改变:在浏览器中通过 window.matchMediawindow.onresize 来监听屏幕的切换或调整。

动态检测刷新率:通过 requestAnimationFrame 进行帧率检测时,确保每次移动到不同的显示器时重新计算帧率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
if (window.localStorage.getItem("fpson") == undefined || window.localStorage.getItem("fpson") == "1") {
let frame = 0;
let lastTime = performance.now();
let fpsDisplay = document.getElementById("fps");

const calculateFPS = () => {
let now = performance.now();
frame++;

if (now > 1000 + lastTime) {
let fps = Math.round((frame * 1000) / (now - lastTime));
let kd;
if (fps <= 10) {
kd = `<span style="color:#39c5bb">卡成ppt😭</span>`;
} else if (fps <= 30) {
kd = `<span style="color:#39c5bb">电竞级帧率😓</span>`;
} else if (fps <= 60) {
kd = `<span style="color:#39c5bb">有点难受😨</span>`;
} else if (fps < 90) {
kd = `<span style="color:#39c5bb">不太流畅😥</span>`;
} else if (fps <= 144) {
kd = `<span style="color:#39c5bb">还不错哦😀</span>`;
} else {
kd = `<span style="color:#39c5bb">十分流畅😆</span>`;
}
fpsDisplay.innerHTML = `FPS: ${fps} ${kd}`;
frame = 0;
lastTime = now;
}

requestAnimationFrame(calculateFPS);
};

// 用于检测显示器变化
const updateFPSOnScreenChange = () => {
frame = 0; // 重置帧计数器
lastTime = performance.now(); // 重置时间
};

window.addEventListener("resize", updateFPSOnScreenChange);
window.addEventListener("orientationchange", updateFPSOnScreenChange);

calculateFPS();
} else {
document.getElementById("fps").style = "display:none!important";
}

版本2

这版有bug,每拖动一次浏览器到另一个屏幕,都会增加显示的FPS,且不会下降,来回切换能干到好几千FPS,原因是代码通过 now - lastTime 来计算过去的时间(毫秒),并且在每秒内统计帧数。拖动窗口时可能导致浏览器的 requestAnimationFrame 变得不稳定,进而导致短暂的时间间隔过小,从而导致帧数异常增高。

监听窗口的resize 事件:因为当你拖动窗口时会触发 resize 事件,你可以借此判断当前浏览器是否切换到另一块显示器。

动态计算刷新率:通过 requestAnimationFrame 来重新检测帧率,同时对窗口的移动进行判断,并在合适的时机更新帧率显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
if (window.localStorage.getItem("fpson") == undefined || window.localStorage.getItem("fpson") == "1") {
let frame = 0;
let lastTime = performance.now();
let fpsDisplay = document.getElementById("fps");
let fps = 0;

const calculateFPS = () => {
let now = performance.now();
frame++;

if (now > 1000 + lastTime) {
fps = Math.round((frame * 1000) / (now - lastTime));
let kd;
if (fps <= 10) {
kd = `<span style="color:#39c5bb">卡成ppt😭</span>`;
} else if (fps <= 30) {
kd = `<span style="color:#39c5bb">电竞级帧率😓</span>`;
} else if (fps <= 60) {
kd = `<span style="color:#39c5bb">有点难受😨</span>`;
} else if (fps < 90) {
kd = `<span style="color:#39c5bb">不太流畅😥</span>`;
} else if (fps <= 144) {
kd = `<span style="color:#39c5bb">还不错哦😀</span>`;
} else {
kd = `<span style="color:#39c5bb">十分流畅😆</span>`;
}
fpsDisplay.innerHTML = `FPS: ${fps} ${kd}`;
frame = 0;
lastTime = now;
}

requestAnimationFrame(calculateFPS);
};

// 检测窗口的显示器变化并更新FPS
const updateFPSOnScreenChange = () => {
frame = 0; // 重置帧计数器
lastTime = performance.now(); // 重置时间
fpsDisplay.innerHTML = `FPS: ${fps} (Updating...)`; // 提示刷新率正在更新
setTimeout(() => {
// 强制重新计算帧率并更新
calculateFPS();
}, 500); // 延迟以确保窗口已移动至新的显示器上
};

window.addEventListener("resize", updateFPSOnScreenChange); // 当窗口被拖动时触发

calculateFPS();
} else {
document.getElementById("fps").style = "display:none!important";
}

版本3

还是不行,也存在FPS猛猛飙升的BUG

使用 window.devicePixelRatioscreen 对象监测显示器切换:使用 window.devicePixelRatioscreen.widthscreen.height 等属性来判断是否切换到了另一个显示器,结合 requestAnimationFrame 来更新帧率。

**定期重置 requestAnimationFrame**:在检测到窗口被拖动后,强制重新初始化 requestAnimationFrame,从而让浏览器重新调整其回调频率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
if (window.localStorage.getItem("fpson") == undefined || window.localStorage.getItem("fpson") == "1") {
let frame = 0;
let lastTime = performance.now();
let fpsDisplay = document.getElementById("fps");
let fps = 0;
let currentDevicePixelRatio = window.devicePixelRatio;

const calculateFPS = () => {
let now = performance.now();
frame++;

if (now - lastTime < 16) {
requestAnimationFrame(calculateFPS);
return;
}

if (now > 1000 + lastTime) {
fps = Math.round((frame * 1000) / (now - lastTime));
let kd;
if (fps <= 10) {
kd = `<span style="color:#39c5bb">卡成ppt😭</span>`;
} else if (fps <= 30) {
kd = `<span style="color:#39c5bb">电竞级帧率😓</span>`;
} else if (fps <= 60) {
kd = `<span style="color:#39c5bb">有点难受😨</span>`;
} else if (fps < 90) {
kd = `<span style="color:#39c5bb">不太流畅😥</span>`;
} else if (fps <= 144) {
kd = `<span style="color:#39c5bb">还不错哦😀</span>`;
} else {
kd = `<span style="color:#39c5bb">十分流畅😆</span>`;
}
fpsDisplay.innerHTML = `FPS: ${fps} ${kd}`;
frame = 0;
lastTime = now;
}

requestAnimationFrame(calculateFPS);
};

// 检测屏幕切换
const checkScreenChange = () => {
if (window.devicePixelRatio !== currentDevicePixelRatio) {
currentDevicePixelRatio = window.devicePixelRatio;
updateFPSOnScreenChange();
}
};

// 检测窗口的显示器变化并更新FPS
const updateFPSOnScreenChange = () => {
frame = 0; // 重置帧计数器
lastTime = performance.now(); // 重置时间
fpsDisplay.innerHTML = `FPS: ${fps} (Updating...)`; // 提示刷新率正在更新
setTimeout(() => {
// 强制重新计算帧率并更新
calculateFPS();
}, 1000); // 延迟1秒,确保窗口已移动至新的显示器上
};

// 监听窗口的resize事件(拖动窗口时)
window.addEventListener("resize", updateFPSOnScreenChange);

// 监听窗口失去焦点和重新获得焦点事件,防止requestAnimationFrame暂停时的异常
window.addEventListener('blur', () => {
frame = 0;
lastTime = performance.now();
});

window.addEventListener('focus', () => {
frame = 0;
lastTime = performance.now();
});

// 定期检查屏幕切换
setInterval(checkScreenChange, 1000);

// 开始计算FPS
calculateFPS();
} else {
document.getElementById("fps").style = "display:none!important";
}

Google浏览器帧渲染统计方法(失败)

这是google浏览器自带的一个开发工具,可以用来监测浏览器的帧率,打开方法如下

image-20240909151731346

显示效果如下:主显示屏160刷新率,正常

image-20240909151928491

切换到120刷新率的屏幕依然显示160,异常,所以,google也不怎么样

image-20240909152113793

Edge浏览器没找到帧率检测的工具,不知道实际怎么样