Анимация с 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 — локальная установка не требуется.
Все уроки этого курса
- Настройка контекста Canvas
- Рисование фигур и контуров
- Работа с изображениями и текстом
- Анимация с requestAnimationFrame