0Pricing
JavaScript Academy · 课时

使用 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 设置 Canvas 上下文
  2. 绘制形状和路径
  3. 处理图像和文本
  4. 使用 requestAnimationFrame 制作动画
← 返回 JavaScript Academy