Синхронизация анимаций в Lottie Web опирается на внутреннюю временную модель, в которой ключевыми сущностями выступают кадры (frames), частота кадров (fps) и длительность композиции. Любая анимация интерпретируется как дискретная последовательность кадров, привязанная к шкале времени.
Основные параметры:
totalFrames / frameRateКаждый экземпляр анимации фактически работает как независимый таймлайн, который может быть управляем извне через API управления воспроизведением.
Синхронизация нескольких Lottie-анимаций начинается с унификации управления их состоянием.
Ключевые методы:
play() — запуск с текущего кадраpause() — остановкаstop() — сброс к начальному состояниюgoToAndStop(frame, isFrame) — переход на кадр с
остановкойgoToAndPlay(frame, isFrame) — переход и запускsetSpeed(value) — изменение скорости
воспроизведенияПри синхронизации важна стабильность управления кадрами, а не автономное воспроизведение.
Наиболее устойчивый подход основан на введении единого временного источника, который управляет несколькими анимациями одновременно.
Вместо работы с кадрами напрямую используется нормализованный коэффициент:
progress = currentTime / duration
Каждая анимация получает одинаковое значение прогресса и преобразует его в кадры:
frame = progress * totalFrames
const animations = [anim1, anim2, anim3];
const duration = 4000;
const start = performance.now();
function tick(now) {
const elapsed = now - start;
const progress = (elapsed % duration) / duration;
animations.forEach(anim => {
const frame = progress * anim.totalFrames;
anim.goToAndStop(frame, true);
});
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
Такой подход исключает расхождение таймингов между анимациями.
Lottie предоставляет событие enterFrame, позволяющее
синхронизировать логику на уровне каждого кадра.
Каждый тик анимации генерирует событие, содержащее текущий кадр. Это позволяет использовать одну анимацию как «мастер», а остальные — как ведомые.
master.addEventListener('enterFrame', (e) => {
const frame = e.currentTime;
slave1.goToAndStop(frame, true);
slave2.goToAndStop(frame, true);
});
Такой подход эффективен при одинаковых или близких композициях.
Модель синхронизации часто строится на разделении ролей:
Метод setSpeed позволяет унифицировать темп анимаций без
ручного управления кадрами.
animations.forEach(anim => {
anim.setSpeed(1);
});
Однако одинаковая скорость не гарантирует фазовую синхронность. Для точного выравнивания используется комбинирование с установкой прогресса или кадров.
Lottie поддерживает воспроизведение сегментов анимации:
anim.playSegments([10, 60], true);
Синхронизация нескольких анимаций через сегменты требует унификации диапазонов:
Сегменты применяются для:
Для высокоточной синхронизации используется внешний цикл рендеринга.
Все анимации отключаются от собственного таймера и управляются единым циклом.
function loop() {
const t = performance.now();
const frame = (t / 16.666) % anim.totalFrames;
anim1.goToAndStop(frame, true);
anim2.goToAndStop(frame, true);
requestAnimationFrame(loop);
}
При длительной работе анимаций возникает проблема временного дрейфа:
Для устранения дрейфа используется периодическая коррекция.
const masterFrame = master.currentFrame;
slaves.forEach(anim => {
anim.goToAndStop(masterFrame, true);
});
Коррекция выполняется не каждый кадр, а через фиксированные интервалы времени:
При управлении несколькими анимациями в интерфейсе важна синхронизация с видимостью.
Анимации могут:
observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
anim.play();
} else {
anim.pause();
}
});
});
При синхронизации с аудиопотоком используется Web Audio API как источник абсолютного времени.
const audioTime = audioContext.currentTime;
const frame = audioTime * fps;
anim.goToAndStop(frame, true);
Аудио обеспечивает более стабильную временную шкалу, чем requestAnimationFrame.
При работе с различными Lottie-композициями возникает задача нормализации:
Все анимации приводятся к единому диапазону:
progress ∈ [0, 1]
И затем масштабируются индивидуально:
frame_i = progress * totalFrames_i
В сложных сценах применяется иерархия:
Каждый уровень может модифицировать прогресс:
Используются следующие подходы:
При пропуске frames система может:
Используется пересчёт на основе абсолютного времени, а не инкрементального:
frame = (performance.now() - start) * fps / 1000
В устойчивой архитектуре синхронизация Lottie-анимаций строится на следующих принципах:
goToAndStop