Приоритеты выполнения

Popmotion построена вокруг предсказуемого цикла обновлений, где каждый активный процесс (анимация, физическая симуляция, действие) синхронизируется с кадровым таймером браузера. Основной принцип — единый источник времени и последовательная обработка всех подписчиков в рамках одного кадра.


Кадровый цикл и базовый планировщик

В основе лежит привязка к requestAnimationFrame, где каждый тик представляет собой атомарную единицу обновления. Внутри этого тика выполняется несколько стадий:

  • сбор активных анимаций
  • вычисление времени шага
  • обновление состояния всех активных сущностей
  • вызов подписчиков (listeners)
  • применение побочных эффектов (например, запись в DOM через styler)

Ключевой момент: порядок выполнения внутри одного кадра детерминирован и не зависит от того, когда была создана анимация — важен момент её регистрации в системе.


Приоритеты источников времени

В Popmotion существует различие между типами обновлений, которые конкурируют за один и тот же кадр:

  • физические процессы (spring, decay)
  • интерполяционные анимации (tween)
  • пользовательские actions
  • цепочки трансформаций (compositions)

Физические модели часто требуют более точного интегрирования времени, поэтому их обновление происходит на основе непрерывного delta-time, тогда как tween-значения могут вычисляться дискретно от начала анимации.

Это создаёт неявный приоритет: более “жёсткие” физические модели получают более раннее и точное обновление состояния внутри одного кадра.


Очередь выполнения actions

Каждое действие в системе регистрируется как подписчик планировщика. Внутри одного кадра формируется очередь:

  1. активные spring-анимации
  2. decay-процессы
  3. timeline и keyframe-последовательности
  4. пользовательские actions

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


Конфликт обновлений и перезапись значений

Когда несколько источников пытаются обновить одно и то же свойство (например, x или opacity), применяется стратегия “последний записавший выигрывает” в рамках одного кадра.

Однако фактический результат зависит от порядка регистрации:

  • более ранний источник в очереди может быть перезаписан более поздним
  • физические модели часто перезаписывают tween-значения, если оба активны одновременно
  • chained actions могут полностью заменить предыдущее значение перед финальной фиксацией кадра

Синхронизация через framesync

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

На уровне архитектуры происходит:

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

Такой подход минимизирует layout thrashing и предотвращает промежуточные визуальные артефакты.


Приоритеты внутри timeline

Timeline-структуры обладают собственной системой упорядочивания:

  • ключевые кадры обрабатываются строго по времени
  • overlapping-анимации разрешаются через порядок добавления
  • сегменты с одинаковым временем запускаются последовательно

Если несколько сегментов имеют одинаковую временную метку, приоритет определяется порядком их вставки в timeline, а не логикой значений.


Прерывание и перезапуск анимаций

При запуске новой анимации на том же свойстве происходит контроль конфликтов:

  • текущая активная анимация может быть остановлена
  • либо переведена в состояние interrupted
  • либо оставлена параллельно при отсутствии пересечения целей

Приоритет отдаётся последнему явно запущенному action, если он затрагивает те же свойства и имеет активную регистрацию в планировщике.


Иерархия вложенных действий

Сложные композиции действий формируют вложенные уровни выполнения:

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

Это создаёт многоуровневую модель приоритизации, где внутренние состояния вычисляются раньше, чем становятся видимыми внешнему уровню.


Конкуренция синхронных и асинхронных источников

Синхронные вызовы внутри одного кадра имеют более высокий приоритет, чем отложенные обновления. Асинхронные события (например, промисы или внешние события UI) попадают в систему только на границе нового кадра, что исключает разрыв консистентности состояния.


Стабилизация итогового состояния кадра

Финальная стадия каждого цикла включает фиксацию состояния:

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

На этом этапе система гарантирует, что каждый наблюдатель получает согласованное состояние без частичных обновлений.


Поведение при высокой нагрузке

При перегрузке анимационной очереди система сохраняет приоритетность:

  • критические физические модели продолжают обновляться
  • менее важные tween-процессы могут деградировать по частоте обновления
  • лишние подписчики исключаются из текущего кадра при необходимости оптимизации

Такой механизм предотвращает потерю плавности базовых анимаций при большом количестве параллельных процессов.


Влияние порядка регистрации на итоговое поведение

Порядок добавления actions в систему напрямую влияет на итоговый результат кадра:

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

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