Понимание rendering pipeline

Архитектура цикла анимации

Рендеринг в mo.js строится вокруг непрерывного цикла обновления состояния анимаций, синхронизированного с браузерным кадром через requestAnimationFrame. Каждый кадр представляет собой пересборку визуального состояния всех активных сущностей: форм, твинов, таймлайнов и эффектов.

Базовый цикл включает три ключевых этапа:

  • Обновление времени (time progression)
  • Интерполяция свойств (tweening)
  • Рендер состояния (render pass)

Система не использует фиксированные временные шаги; вместо этого применяется time-based animation, где ключевым параметром выступает абсолютное или относительное время.


Синхронизация с requestAnimationFrame

Движок анимации интегрирован в цикл отрисовки браузера:

  • каждый кадр получает timestamp от requestAnimationFrame
  • вычисляется delta между текущим и предыдущим кадром
  • обновляются все активные экземпляры анимаций

Ключевая особенность — отсутствие привязки к FPS. Это обеспечивает стабильность анимации при изменении нагрузки на систему.

Основное уравнение временного шага:

  • t = currentTime - startTime

На основе этого значения вычисляется прогресс анимации:

  • progress = t / duration

Система нормализации прогресса

Каждая анимация переводит абсолютное время в нормализованный диапазон:

  • 0 → 1 для стандартного цикла
  • возможны расширенные диапазоны при repeat и yoyo режимах

Нормализованный прогресс проходит через функции easing:

  • linear
  • ease.in
  • ease.out
  • elastic
  • bounce

Easing-функции являются чистыми математическими преобразованиями:

  • p' = easing(p)

Это значение становится основой для всех последующих вычислений свойств.


Интерполяция свойств (tween engine)

Каждый анимируемый параметр проходит через систему интерполяции.

Поддерживаются типы значений:

  • числа (opacity, scale, radius)
  • цвета (rgb, hex → interpolated channels)
  • трансформации (translate, rotate, scale)
  • массивы (path points, stagger values)

Общий принцип интерполяции:

  • value = start + (end - start) * easedProgress

Для сложных типов применяется декомпозиция:

Цвета

Цвет разбивается на каналы:

  • R
  • G
  • B
  • A (если доступно)

Интерполяция происходит отдельно по каждому каналу, затем собирается обратно.

Трансформации

Матрицы преобразований вычисляются последовательно:

  • translate
  • rotate
  • scale

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


Объекты анимации и состояние

Каждый анимируемый элемент хранит внутреннее состояние:

  • duration
  • delay
  • repeat count
  • easing function
  • current progress
  • isActive flag

Состояние обновляется на каждом кадре и не пересоздаётся, что снижает нагрузку на GC.

Особенность архитектуры — разделение:

  • декларативного описания анимации
  • и runtime-состояния

Timeline и композиция

Timeline является контейнером для синхронизации нескольких анимаций.

Он управляет:

  • стартом групп анимаций
  • задержками между ними
  • последовательным или параллельным запуском

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

Основные режимы:

  • parallel execution
  • sequential chaining
  • offset-based scheduling

Burst система

Burst представляет собой генератор множества однотипных анимаций.

При активации:

  • создаётся набор экземпляров shape/tween
  • каждому назначается индивидуальный offset времени
  • применяется вариативность параметров (stagger)

Pipeline burst-а:

  1. генерация конфигурации
  2. клонирование шаблонов
  3. распределение временных смещений
  4. регистрация в основном цикле рендера

Stagger и распределение времени

Stagger используется для создания эффекта последовательного старта анимаций.

Алгоритм:

  • базовое время запуска
  • индекс элемента
  • коэффициент задержки

Формула:

  • delay = index * staggerStep

Это формирует каскадное развертывание анимаций без дополнительных таймеров.


Рендеринг DOM/SVG состояния

Визуальное представление обновляется через синхронизацию вычисленных значений со свойствами элементов:

  • transform → CSS transform attribute
  • opacity → style.opacity
  • geometry → SVG attributes (r, cx, cy, path d)

Обновление происходит батчингом в пределах одного кадра:

  • сначала вычисляются все значения
  • затем применяется единый render pass

Это предотвращает layout thrashing.


Оптимизация и минимизация перерасчётов

Pipeline оптимизирован через несколько механизмов:

Dirty checking

Обновляются только изменённые свойства.

Memoization easing

Результаты easing-функций кэшируются для одинаковых прогресс-значений.

Object pooling

Экземпляры анимаций переиспользуются вместо постоянного создания новых объектов.

Batch rendering

Все DOM/SVG изменения применяются в одном блоке операций.


Обработка завершения анимации

Завершение определяется условием:

  • progress >= 1

Далее применяются правила:

  • repeat → сброс прогресса
  • yoyo → инверсия направления
  • remove → удаление из pipeline

Завершённые анимации исключаются из основного цикла обновления.


Приоритеты и очередь исполнения

При наличии большого количества анимаций формируется очередь обновления:

  • high priority (timeline control)
  • normal (shape animation)
  • low (decorative bursts)

Это предотвращает блокировку кадра при перегрузке сценами высокой плотности.


Связь с математической моделью движения

Каждая анимация может быть интерпретирована как функция времени:

  • f(t) → visual state

Pipeline фактически реализует дискретизацию непрерывной функции движения, где каждый кадр является сэмплом функции.


Обработка сложных сцен

При большом количестве объектов применяется:

  • разбиение на группы
  • частичное обновление сцен
  • приоритизация видимых элементов

Это снижает стоимость полного прохода сцены и стабилизирует FPS при высокой нагрузке.