用requestanimationframe实现角色帧动画需按屏幕刷新节奏逐帧切换并循环回第一帧;预加载图片,用时间差控制帧率(如12fps),通过取模运算实现自动循环,配合canvas绘制,注意暂停控制与多动作独立索引管理。

用 requestAnimationFrame 实现游戏角色帧动画循环播放,核心是**按屏幕刷新节奏逐帧切换图片/精灵图索引,并在最后一帧后自动回到第一帧**,避免卡顿、掉帧和时间误差。
准备动画资源与基础状态
先确保你有一组连续的帧图像(如 player_0.png 到 player_3.png),或一张包含所有帧的精灵图(Sprite Sheet)。同时定义关键变量:
-
帧数组:例如
const frames = ['player_0.png', 'player_1.png', 'player_2.png', 'player_3.png']; -
当前帧索引:如
let currentFrame = 0; - 帧率控制(可选但推荐):通过时间差限制每秒播放多少帧,比如固定 12 FPS(即每 ~83ms 切一帧)
用 requestAnimationFrame 驱动循环更新
不要用 setInterval,而是用 requestAnimationFrame 获取高精度时间戳,在每次回调中计算是否该切帧:
let lastTime = 0;
const frameDuration = 1000 / 12; // 12 FPS → 每帧约 83.3ms
<p>function animate(currentTime) {
if (currentTime - lastTime >= frameDuration) {
currentFrame = (currentFrame + 1) % frames.length;
lastTime = currentTime;
// 更新画面:比如 drawImage(frames[currentFrame], x, y)
}
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);</p>
绘制当前帧(Canvas 示例)
假设你用 <canvas></canvas> 渲染,每次更新后调用绘图逻辑:
- 清空画布:
ctx.clearRect(0, 0, canvas.width, canvas.height); - 加载并绘制当前帧图片(需预加载):
ctx.drawImage(imgs[currentFrame], x, y, width, height); - 若用精灵图,改用
drawImage(sprite, sx, sy, sw, sh, dx, dy, dw, dh)截取对应区域
注意事项与优化点
关键细节不能漏:
-
图片必须预加载完成再启动动画,否则会闪白或跳帧(可用
Promise.all(frames.map(src => loadImage(src)))) -
暂停/恢复支持:用布尔变量
isPlaying控制是否执行帧更新逻辑 -
不同动作独立控制:跑步、跳跃、攻击可各自维护
currentFrame和lastTime,切换动作时重置索引 -
避免重复请求:确保只调用一次
requestAnimationFrame(animate)启动,函数内递归调用即可
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











