Popmotion построена вокруг предсказуемого цикла обновлений, где каждый активный процесс (анимация, физическая симуляция, действие) синхронизируется с кадровым таймером браузера. Основной принцип — единый источник времени и последовательная обработка всех подписчиков в рамках одного кадра.
В основе лежит привязка к requestAnimationFrame, где
каждый тик представляет собой атомарную единицу обновления. Внутри этого
тика выполняется несколько стадий:
Ключевой момент: порядок выполнения внутри одного кадра детерминирован и не зависит от того, когда была создана анимация — важен момент её регистрации в системе.
В Popmotion существует различие между типами обновлений, которые конкурируют за один и тот же кадр:
Физические модели часто требуют более точного интегрирования времени, поэтому их обновление происходит на основе непрерывного delta-time, тогда как tween-значения могут вычисляться дискретно от начала анимации.
Это создаёт неявный приоритет: более “жёсткие” физические модели получают более раннее и точное обновление состояния внутри одного кадра.
Каждое действие в системе регистрируется как подписчик планировщика. Внутри одного кадра формируется очередь:
Такой порядок обеспечивает стабильность поведения сложных сцен, где несколько анимационных систем влияют на один и тот же набор свойств.
Когда несколько источников пытаются обновить одно и то же свойство
(например, x или opacity), применяется
стратегия “последний записавший выигрывает” в рамках одного кадра.
Однако фактический результат зависит от порядка регистрации:
Слой синхронизации обеспечивает консолидацию всех обновлений в рамках одного временного окна. Это устраняет дрейф состояния между разными типами анимаций.
На уровне архитектуры происходит:
Такой подход минимизирует layout thrashing и предотвращает промежуточные визуальные артефакты.
Timeline-структуры обладают собственной системой упорядочивания:
Если несколько сегментов имеют одинаковую временную метку, приоритет определяется порядком их вставки в timeline, а не логикой значений.
При запуске новой анимации на том же свойстве происходит контроль конфликтов:
Приоритет отдаётся последнему явно запущенному action, если он затрагивает те же свойства и имеет активную регистрацию в планировщике.
Сложные композиции действий формируют вложенные уровни выполнения:
Это создаёт многоуровневую модель приоритизации, где внутренние состояния вычисляются раньше, чем становятся видимыми внешнему уровню.
Синхронные вызовы внутри одного кадра имеют более высокий приоритет, чем отложенные обновления. Асинхронные события (например, промисы или внешние события UI) попадают в систему только на границе нового кадра, что исключает разрыв консистентности состояния.
Финальная стадия каждого цикла включает фиксацию состояния:
На этом этапе система гарантирует, что каждый наблюдатель получает согласованное состояние без частичных обновлений.
При перегрузке анимационной очереди система сохраняет приоритетность:
Такой механизм предотвращает потерю плавности базовых анимаций при большом количестве параллельных процессов.
Порядок добавления actions в систему напрямую влияет на итоговый результат кадра:
Эта особенность делает систему чувствительной к архитектуре кода, особенно при построении сложных анимационных графов.