0Pricing
JavaScript Academy · Урок

Анимация с requestAnimationFrame

Создавайте плавные анимации на canvas.

«Анимация с requestAnimationFrame» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.

Зачем нужен requestAnimationFrame

requestAnimationFrame(callback) планирует выполнение функции рисования перед следующим обновлением экрана — обычно 60 раз в секунду. В неактивных вкладках он приостанавливается, экономя CPU и заряд батареи, в отличие от setInterval.

function frame() {
  // draw one frame
  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);

Основной цикл

Цикл анимации очищает canvas, обновляет состояние, рисует, а затем снова планирует своё выполнение.

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 возвращает идентификатор. Передайте его в 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();

Советы по производительности

Не создавайте объекты внутри цикла, объединяйте вызовы рисования и по возможности перерисовывайте только изменившиеся области. Сократите работу, выполняемую за кадр, чтобы уложиться примерно в 16 мс при 60 кадрах в секунду.

Быстрая проверка

Проверьте свои знания об анимации.

Повторение: анимация

Вы создали циклы анимации с помощью requestAnimationFrame, очищали каждый кадр с помощью clearRect, использовали метку времени для независимости от частоты кадров, анимировали отскакивающие мячи и несколько объектов, применяли сглаживание и научились останавливать или приостанавливать анимацию с помощью cancelAnimationFrame.

Часто задаваемые вопросы

Урок «Анимация с requestAnimationFrame» бесплатный?

Да — полный текст урока «Анимация с requestAnimationFrame» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.

Чему я научусь в уроке «Анимация с requestAnimationFrame»?

Создавайте плавные анимации на canvas. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать JavaScript Academy?

Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Анимация с requestAnimationFrame»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке JavaScript Academy?

Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Настройка контекста Canvas
  2. Рисование фигур и контуров
  3. Работа с изображениями и текстом
  4. Анимация с requestAnimationFrame
← Назад к JavaScript Academy