Рендеринг в mo.js строится вокруг непрерывного цикла обновления
состояния анимаций, синхронизированного с браузерным кадром через
requestAnimationFrame. Каждый кадр представляет собой
пересборку визуального состояния всех активных сущностей: форм, твинов,
таймлайнов и эффектов.
Базовый цикл включает три ключевых этапа:
Система не использует фиксированные временные шаги; вместо этого применяется time-based animation, где ключевым параметром выступает абсолютное или относительное время.
Движок анимации интегрирован в цикл отрисовки браузера:
requestAnimationFrameКлючевая особенность — отсутствие привязки к FPS. Это обеспечивает стабильность анимации при изменении нагрузки на систему.
Основное уравнение временного шага:
t = currentTime - startTimeНа основе этого значения вычисляется прогресс анимации:
progress = t / durationКаждая анимация переводит абсолютное время в нормализованный диапазон:
0 → 1 для стандартного циклаНормализованный прогресс проходит через функции easing:
Easing-функции являются чистыми математическими преобразованиями:
p' = easing(p)Это значение становится основой для всех последующих вычислений свойств.
Каждый анимируемый параметр проходит через систему интерполяции.
Поддерживаются типы значений:
Общий принцип интерполяции:
value = start + (end - start) * easedProgressДля сложных типов применяется декомпозиция:
Цвет разбивается на каналы:
Интерполяция происходит отдельно по каждому каналу, затем собирается обратно.
Матрицы преобразований вычисляются последовательно:
Порядок операций фиксирован, что исключает неоднозначность результата.
Каждый анимируемый элемент хранит внутреннее состояние:
Состояние обновляется на каждом кадре и не пересоздаётся, что снижает нагрузку на GC.
Особенность архитектуры — разделение:
Timeline является контейнером для синхронизации нескольких анимаций.
Он управляет:
Внутренне timeline также является анимационным объектом, но вместо визуальных свойств управляет временем дочерних сущностей.
Основные режимы:
Burst представляет собой генератор множества однотипных анимаций.
При активации:
Pipeline burst-а:
Stagger используется для создания эффекта последовательного старта анимаций.
Алгоритм:
Формула:
delay = index * staggerStepЭто формирует каскадное развертывание анимаций без дополнительных таймеров.
Визуальное представление обновляется через синхронизацию вычисленных значений со свойствами элементов:
Обновление происходит батчингом в пределах одного кадра:
Это предотвращает layout thrashing.
Pipeline оптимизирован через несколько механизмов:
Обновляются только изменённые свойства.
Результаты easing-функций кэшируются для одинаковых прогресс-значений.
Экземпляры анимаций переиспользуются вместо постоянного создания новых объектов.
Все DOM/SVG изменения применяются в одном блоке операций.
Завершение определяется условием:
progress >= 1Далее применяются правила:
Завершённые анимации исключаются из основного цикла обновления.
При наличии большого количества анимаций формируется очередь обновления:
Это предотвращает блокировку кадра при перегрузке сценами высокой плотности.
Каждая анимация может быть интерпретирована как функция времени:
f(t) → visual statePipeline фактически реализует дискретизацию непрерывной функции движения, где каждый кадр является сэмплом функции.
При большом количестве объектов применяется:
Это снижает стоимость полного прохода сцены и стабилизирует FPS при высокой нагрузке.