Popmotion построена вокруг идеи функциональной композиции: каждая анимация рассматривается как независимый поток значений во времени, который можно преобразовывать, объединять и комбинировать с другими потоками. Это делает систему не набором отдельных эффектов, а конструктором анимационных графов, где поведение формируется через композиционные примитивы.
В основе лежит концепция value stream — непрерывного потока значений, изменяющихся во времени. Любая анимация в Popmotion может быть представлена как функция, которая принимает входное состояние и возвращает новый поток.
Такой подход позволяет:
Композиция здесь не ограничивается последовательным запуском — она работает как математическое объединение функций.
Последовательная композиция используется, когда одна анимация должна начинаться после завершения другой. В Popmotion это достигается через цепочки, где каждый следующий шаг получает управление после завершения предыдущего.
Принцип можно выразить как:
Такой подход применяется для построения сценариев интерфейса, где важно линейное развитие событий: появление элементов, переходы экранов, пошаговые эффекты.
Пример логики:
import { tween, chain } from 'popmotion';
chain(
tween({ from: 0, to: 100, duration: 300 }),
tween({ from: 100, to: 200, duration: 300 }),
tween({ from: 200, to: 300, duration: 300 })
);
Каждый следующий tween получает управление только после завершения предыдущего, формируя линейный поток изменений.
Параллельная композиция позволяет запускать несколько анимаций одновременно, сохраняя независимость их внутренних таймингов. Это базовый инструмент для создания сложных визуальных эффектов, где несколько параметров изменяются синхронно.
Используется, когда:
Логическая модель:
import { tween, parallel } from 'popmotion';
parallel([
tween({ from: 0, to: 100, duration: 500 }),
tween({ from: 0, to: 1, duration: 500 }),
tween({ from: 100, to: 200, duration: 500 })
]);
Параллельная композиция часто используется как базовый слой, к которому добавляются другие композиционные элементы.
Более сложные сценарии требуют комбинирования последовательности и параллельности. Это формирует древовидную структуру анимаций, где узлы могут быть как простыми tween-потоками, так и составными группами.
Например:
Такая структура превращает анимацию в декларативный граф.
Stagger применяется для создания эффектов последовательного запуска элементов с задержкой. В отличие от простой последовательности, здесь шаги перекрываются по времени.
Используется для:
Механика:
import { stagger, tween } from 'popmotion';
stagger(
Array.from({ length: 5 }).map(() =>
tween({ from: 0, to: 1, duration: 400 })
),
100
);
Stagger создает эффект волны, где движение распространяется по группе объектов.
Одним из ключевых механизмов является преобразование одного потока значений в другой. Это позволяет строить цепочки зависимых анимаций.
Типичный сценарий:
Формально:
import { tween, transform } from 'popmotion';
const progress = tween({ from: 0, to: 1, duration: 1000 });
const x = transform(progress, v => v * 300);
const opacity = transform(progress, v => v);
Один поток становится источником для множества визуальных каналов, что снижает необходимость в дублировании анимаций.
Popmotion поддерживает физические анимации (spring, decay), которые особенно полезны при композиции с tween-потоками.
Комбинации используются для:
Типичный паттерн:
Композиционно это выглядит как переход между типами функций движения.
Слияние потоков используется, когда несколько независимых анимаций должны влиять на одно состояние. В отличие от parallel, где потоки существуют отдельно, merge объединяет их выходы.
Используется для:
Модель:
import { merge, tween, spring } from 'popmotion';
merge([
tween({ from: 0, to: 100, duration: 500 }),
spring({ from: 100, to: 0, stiffness: 200 })
]);
Такой подход позволяет строить гибридные системы движения.
Особое место занимает интеграция pointer-событий. В Popmotion ввод сам по себе является потоком значений, который может быть включен в композицию наравне с анимациями.
Сценарии:
Композиционная модель:
Это позволяет создавать системы, где пользовательский ввод и автоматическая анимация не разделены, а существуют в одной структуре.
Сложные интерфейсы формируются как деревья потоков:
Такая структура позволяет:
Пример структуры:
root parallel
chain
stagger
Каждый узел управляет собственным подграфом.
Popmotion позволяет описывать анимации как декларацию переходов между состояниями, а не как последовательность императивных вызовов.
Состояние становится центральной точкой:
Композиция строится как функция преобразования состояния во времени, где каждая часть графа влияет на итоговый результат.
Одна из сложностей композиции — объединение потоков с разной длительностью и природой движения. Решение заключается в нормализации:
Это позволяет объединять:
в одну систему без конфликтов тайминга.
На практике композиция используется для создания повторяемых архитектурных решений:
Каждый паттерн представляет собой устойчивую структуру графа анимаций, а не набор разрозненных эффектов.
Композиция также включает управление зависимостями:
Это формирует причинно-следственные связи внутри графа, где движение не просто параллельно, а логически связано.
Важный принцип — контроль времени передается не центральному таймеру, а самим потокам. Каждый компонент:
Это делает композицию гибкой и расширяемой, так как добавление нового узла не требует изменения всей структуры.