使用 requestAnimationFrame 制作动画
创建流畅的 Canvas 动画。
使用 requestAnimationFrame 制作动画 是 CoddyKit 上的免费 JavaScript Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 JavaScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 JavaScript Academy 课程共包含 4 节课。
为什么使用 requestAnimationFrame
requestAnimationFrame(callback) 会安排您的绘图函数在下一次屏幕重绘前运行,通常每秒运行 60 次。与 setInterval 不同,它会在后台标签页中暂停,从而节省 CPU 和电池电量。
function frame() {
// draw one frame
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);基本循环
动画循环会清除画布、更新状态、进行绘制,然后重新安排自身运行。
let x = 0;
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, 50, 30, 30);
x += 2;
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);清除每个动画帧
如果没有 clearRect,上一帧会保留在画布上,从而产生拖影。请在每一帧的开头清除整个缓冲区,以便干净地重新绘制。
ctx.clearRect(0, 0, canvas.width, canvas.height);时间戳参数
回调会接收一个高分辨率时间戳(毫秒)。请使用它计算帧与帧之间经过的时间。
let last = 0;
function loop(now) {
const dt = now - last;
last = now;
// dt = ms since previous frame
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);不受帧率影响的运动
将速度乘以时间增量,这样无论帧率如何变化,运动速度都能保持一致。
let x = 0;
const speed = 0.1; // px per ms
function loop(now) {
const dt = now - (loop.last || now);
loop.last = now;
x += speed * dt;
requestAnimationFrame(loop);
}让球体反弹
对象碰到边缘时反转速度,使其产生反弹效果。
let x = 50, vx = 3;
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
x += vx;
if (x < 0 || x > canvas.width) vx = -vx;
ctx.beginPath();
ctx.arc(x, 75, 15, 0, Math.PI * 2);
ctx.fill();
requestAnimationFrame(loop);
}
loop();停止循环
requestAnimationFrame 会返回一个 id。将它传给 cancelAnimationFrame 即可停止动画。
let id;
function loop() {
id = requestAnimationFrame(loop);
}
id = requestAnimationFrame(loop);
// later:
cancelAnimationFrame(id);暂停与恢复
请跟踪一个 running 标志。要恢复动画,请请求新帧;要暂停动画,只需停止请求新帧(或取消待处理的请求)。
let running = true;
function loop() {
if (!running) return;
// draw...
requestAnimationFrame(loop);
}
function pause() { running = false; }
function resume() { running = true; requestAnimationFrame(loop); }为多个对象设置动画
将对象存储在数组中,并在循环内更新每个对象。
const balls = [{ x: 10, vx: 2 }, { x: 80, vx: -3 }];
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const b of balls) {
b.x += b.vx;
ctx.fillRect(b.x, 60, 20, 20);
}
requestAnimationFrame(loop);
}
loop();使用缓动实现平滑运动
使用缓动向 target 进行插值,从而实现自然减速。
let x = 0;
const target = 200;
function loop() {
x += (target - x) * 0.1; // ease out
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, 50, 30, 30);
if (Math.abs(target - x) > 0.5) requestAnimationFrame(loop);
}
loop();性能建议
避免在循环内分配对象,批量执行绘制调用,并尽可能只重绘发生变化的内容。请减少每帧的工作量,以保持在每秒 60 帧所需的约 16ms 预算以内。
快速检查
测试您对动画的了解。
回顾:动画
您使用 requestAnimationFrame 构建了动画循环,使用 clearRect 清除每一帧,利用时间戳实现不受帧率影响的动画,让反弹的 balls 和多个对象动起来,应用了缓动,并学会使用 cancelAnimationFrame 停止或暂停动画。
常见问题解答
「使用 requestAnimationFrame 制作动画」课时是免费的吗?
是的 — 「使用 requestAnimationFrame 制作动画」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 JavaScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 JavaScript Academy 课程共包含 4 节课。
「使用 requestAnimationFrame 制作动画」这节课中我会学到什么?
创建流畅的 Canvas 动画。 你通过在浏览器中直接运行的动手代码来练习 JavaScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 JavaScript Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 JavaScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「使用 requestAnimationFrame 制作动画」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 JavaScript Academy 课中编写并运行代码吗?
能。每节 JavaScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 设置 Canvas 上下文
- 绘制形状和路径
- 处理图像和文本
- 使用 requestAnimationFrame 制作动画