文章目录
动画是由一系列叫做“帧”(frame)的图像组成的,这些图像的显示频率就叫做“帧速率”(frame rate)。通常来说,有必要计算一下帧速率。在实现“基于时间的运动”效果时,可能会用到动画的帧速率,或是有时为了保证动画能够播放得足够流畅,我们也需要知道动画的帧速率。
下面应用程序可以算出动画的帧速率,并将它显示在 canvas 之中。
应用程序的代码将上次绘制动画帧的时间从当前时间中减去,得到了这两帧动画的时间差,然后再用 1000 除以这个以毫秒为单位的时间差,于是就得出了动画每秒钟播放的帧数,也就是其帧速率。
关键逻辑:fps = 1000 / (currentTime - lastTime)
currentTime 来源于 requestAnimationFrame为animate方法返回的当前帧时间戳 time,time 是从 requestAnimationFrame 开始执行时递增的,并不是 Date.now() 的时间戳。其值的示例:“26.8、43.5、60.1、76.8”,单位是毫秒。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>5-11-帧速率的计算</title>
<style>
body {
background: #eeeeee;
}
#canvas {
background: #ffffff;
margin-top: 5px;
margin-left: 10px;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('canvas'),
context = canvas.getContext('2d')
// 记录上一帧时间戳和FPS计算缓冲区
let lastTime = performance.now()
const FPS_BUFFER_SIZE = 10 // 取10帧的平均值
let fpsBuffer = []
/**
* 计算平滑的FPS值
* @param {number} currentTime - 当前帧的时间戳(performance.now()获取的值)
* @returns {number} - 返回最近10帧的平均FPS值,若无法计算则返回0
*/
function calculateFPS(currentTime) {
// 计算当前帧的瞬时FPS值(1000ms/帧间隔时间)
const fps = 1000 / (currentTime - lastTime)
lastTime = currentTime
// 维护一个固定长度的FPS缓冲区(最近10帧)
fpsBuffer.push(fps)
if (fpsBuffer.length > FPS_BUFFER_SIZE) {
fpsBuffer.shift()
}
// 计算缓冲区中FPS的平均值,确保返回有效数字
const avgFPS = fpsBuffer.reduce((sum, val) => sum + val, 0) / fpsBuffer.length
return isFinite(avgFPS) ? avgFPS : 0
}
/**
* 动画循环函数,每帧清除画布并显示当前FPS
* @param {number} time - requestAnimationFrame提供的当前帧时间戳
*/
function animate(time) {
// 清除上一帧内容
context.clearRect(0, 0, canvas.width, canvas.height)
// 在画布左上角显示FPS数值
context.fillStyle = '#000'
context.font = '20px Arial'
context.fillText('FPS: ' + calculateFPS(time).toFixed(), 10, 20)
// 请求下一帧动画
requestAnimationFrame(animate)
}
requestAnimationFrame(animate)
</script>
</body>
</html>