【第5章 动画】5.2 帧速率的计算

发布于:2025-06-27 ⋅ 阅读:(17) ⋅ 点赞:(0)

文章目录


动画是由一系列叫做“帧”(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>

网站公告

今日签到

点亮在社区的每一天
去签到