Временная шкала и keyframes

В основе анимаций Lottie лежит дискретная временная шкала, построенная вокруг кадровой модели, унаследованной от Adobe After Effects. Вся анимация описывается не как непрерывное изменение во времени, а как набор ключевых состояний, привязанных к конкретным кадрам композиции.

Модель времени: кадры и длительность композиции

Каждая Lottie-анимация содержит композицию, определяющую базовые параметры временной шкалы:

  • fr (frame rate) — количество кадров в секунду
  • ip (in point) — начальный кадр композиции
  • op (out point) — конечный кадр композиции
  • markers (опционально) — метки для сегментов анимации

Длительность анимации вычисляется как разница между op и ip, переведённая в секунды через frame rate:

duration (sec) = (op - ip) / fr

В Lottie Web внутренняя шкала чаще оперирует кадрами, а не миллисекундами, что делает поведение строго детерминированным при рендеринге.


Ключевые кадры (Keyframes) как основа анимации

Любое изменяемое свойство в Lottie представляется через набор ключевых кадров. Ключевой кадр описывает состояние свойства в конкретный момент времени.

Базовая структура keyframe:

{
  "t": 10,
  "s": [100, 100],
  "e": [200, 200],
  "i": { "x": [0.42], "y": [1] },
  "o": { "x": [0.58], "y": [0] }
}

Основные поля keyframe

  • t — время (в кадрах)
  • s — start value (начальное значение)
  • e — end value (конечное значение)
  • i — incoming bezier handle (входящая кривая)
  • o — outgoing bezier handle (исходящая кривая)

Если ключевой кадр единственный, используется только s, а интерполяция отсутствует.


Интерполяция и easing-модель

Lottie использует кривые Безье для описания плавности переходов между ключевыми кадрами. В отличие от линейной интерполяции, easing задаётся вручную через control points.

Математическая модель

Каждый переход между кадрами можно представить как функцию:

p(t) = (1 - t)^3 * P0 + 3(1 - t)^2 t * P1 + 3(1 - t) t^2 * P2 + t^3 * P3

Где:

  • P0 — начальное значение
  • P3 — конечное значение
  • P1, P2 — контрольные точки из o и i

Структура анимируемых свойств

В Lottie почти любое свойство может быть анимировано:

Transform (ks)

"ks": {
  "o": { "k": 100 },
  "r": { "k": 45 },
  "p": { "k": [540, 960, 0] },
  "a": { "k": [0, 0, 0] },
  "s": { "k": [100, 100, 100] }
}
  • o — opacity
  • r — rotation
  • p — position
  • a — anchor point
  • s — scale

Каждое поле может быть либо статическим значением, либо массивом keyframes.


Линейная и нелинейная анимация

Если свойство содержит простой массив значений:

"s": {
  "k": [
    { "t": 0, "s": [0, 0] },
    { "t": 20, "s": [100, 100] }
  ]
}

то движение интерпретируется как анимация между точками времени.

Если присутствуют i и o, используется cubic easing.


Временная шкала в Lottie Web

В Lottie Web временная шкала доступна через объект animationItem, возвращаемый после загрузки анимации:

import lottie from "lottie-web";

const anim = lottie.loadAnimation({
  container: document.getElementById("app"),
  renderer: "svg",
  loop: true,
  autoplay: false,
  path: "animation.json"
});

Управление текущим временем

Перемещение по кадрам

anim.goToAndStop(30, true);
  • первый аргумент — кадр
  • второй — использование кадровой шкалы (true) или времени (false)
anim.goToAndPlay(10, true);

Управление сегментами временной шкалы

Сегменты позволяют проигрывать части анимации:

anim.playSegments([0, 50], true);

Сегменты особенно важны для сложных анимаций интерфейсов, где одна композиция содержит несколько состояний.


Синхронизация с внешним временем

anim.currentFrame;
anim.totalFrames;
anim.currentTime;
  • currentFrame — текущий кадр
  • totalFrames — общее число кадров
  • currentTime — время в секундах

События временной шкалы

Lottie Web предоставляет доступ к внутреннему циклу проигрывания:

anim.addEventListener("enterFrame", (e) => {
  console.log(e.currentTime);
});

Основные события

  • enterFrame — вызывается на каждом кадре
  • loopComplete — завершение цикла
  • complete — завершение анимации (если loop = false)
  • segmentStart / segmentComplete — работа с сегментами

Внутренняя модель интерполяции Lottie Web

Во время рендеринга движок выполняет несколько этапов:

  1. Определение текущего кадра
  2. Поиск ближайших keyframes
  3. Вычисление интерполяции значений
  4. Применение transform к DOM/SVG/Canvas
  5. Рендер слоя

Для SVG-рендерера это означает динамическое обновление атрибутов элементов DOM на каждом кадре.


Keyframes и сложные типы данных

Цвет

"c": {
  "k": [
    { "t": 0, "s": [1, 0, 0] },
    { "t": 20, "s": [0, 0, 1] }
  ]
}

Цвета интерполируются по RGB-компонентам.


Маски и пути

Пути используют набор вершин, где каждая точка также может анимироваться:

"ks": {
  "k": [
    {
      "t": 0,
      "s": [[0,0],[100,100]],
      "i": [[0,0],[0,0]],
      "o": [[0,0],[0,0]]
    }
  ]
}

Каждый сегмент пути интерполируется отдельно.


Связь After Effects и Lottie keyframes

Экспорт через Bodymovin преобразует AE-анимацию в JSON:

  • position → p
  • rotation → r
  • scale → s
  • opacity → o

Ease curves из AE конвертируются в bezier handles (i, o).

Особенность модели: After Effects допускает выражения и time-remapping, но Lottie фиксирует результат в виде дискретных ключевых кадров.


Time remapping и его влияние на шкалу

Time remapping в AE преобразуется в пересчёт временной шкалы слоя:

  • исходная шкала заменяется пользовательской функцией времени
  • keyframes смещаются относительно новой временной оси

В Lottie это выражается через пересчитанные значения t без сохранения исходной функции ремаппинга.


Практическая модель управления временной шкалой

Lottie Web не предоставляет полноценного API редактирования keyframes на лету, но позволяет:

  • перемещать playhead
  • обрезать сегменты
  • изменять скорость
  • синхронизировать внешний таймер
anim.setSpeed(2); // ускорение в 2 раза

Ограничения временной модели

  • отсутствует полноценный runtime keyframe editor
  • нет динамического пересчёта AE expressions
  • фиксированная кадровая сетка
  • интерполяция ограничена cubic bezier моделью

Поведение при разных renderer

SVG renderer

  • каждый кадр обновляет DOM
  • высокая точность трансформаций
  • более высокая нагрузка при сложных сценах

Canvas renderer

  • отрисовка через bitmap
  • стабильная производительность
  • меньше точности на сложных путях

HTML renderer

  • используется редко
  • анимация DOM-элементов напрямую

Синхронизация нескольких анимаций

При работе с несколькими Lottie-инстансами временная шкала может синхронизироваться вручную:

const t = masterAnim.currentFrame;

slaveAnim.goToAndStop(t, true);

Это создаёт единый временной контур между композициями.


Принципы детерминированности

Ключевая особенность временной модели Lottie:

  • одинаковые keyframes → одинаковый результат на любом устройстве
  • отсутствие случайных факторов рендера
  • строгая привязка к frame rate

Это делает систему подходящей для UI-анимаций, где важна воспроизводимость состояния.