Popmotion строится вокруг функционального подхода, в котором каждая анимация представлена как независимая сущность, а не как метод объекта или класс. Основной принцип заключается в том, что поведение описывается функциями, которые принимают входные данные и возвращают поток значений во времени.
Такой подход формирует стиль, в котором отсутствует состояние, скрытое внутри объектов, а управление анимацией становится явным и композиционным.
Ключевая особенность:
import { tween } from 'popmotion';
const animation = tween({
from: 0,
to: 300,
duration: 1000
});
animation.start(v => {
console.log(v);
});
Здесь анимация не привязана к DOM или объекту — она производит поток чисел, который можно использовать в любом контексте.
Одной из фундаментальных идей Popmotion является разделение вычисления значений и их применения к интерфейсу. Значения генерируются независимо, а привязка к DOM выполняется отдельно через styler.
import { tween, styler } from 'popmotion';
const box = document.querySelector('.box');
const boxStyler = styler(box);
tween({
from: 0,
to: 200,
duration: 500
}).start(v => {
boxStyler.set('x', v);
});
Такой стиль устраняет жёсткую связь между анимационной логикой и представлением. Один и тот же tween может быть применён к canvas, DOM или WebGL.
Popmotion поощряет композицию простых анимационных примитивов вместо создания сложных монолитных систем. Основные примитивы:
Композиция происходит через вложенные вызовы и обработчики.
import { spring, tween } from 'popmotion';
spring({
from: 0,
to: 1,
stiffness: 200
}).start(v => {
console.log('spring:', v);
});
Композиционный стиль проявляется в том, что анимации легко заменяются без изменения остального кода:
const animation = spring({ from: 0, to: 500 });
// легко заменить на tween без изменения потребителя
Popmotion использует модель, близкую к реактивному программированию, где каждое значение проходит через цепочку обработчиков.
import { tween } from 'popmotion';
tween({
from: 0,
to: 100
}).start({
update: v => console.log(v),
complete: () => console.log('done')
});
Разделение update/complete делает код более декларативным: логика реакции отделена от генерации значений.
Pointer в Popmotion — это не просто обработчик событий мыши или касаний, а поток координат, который интегрируется в общий стиль анимаций.
import { pointer } from 'popmotion';
pointer().start(v => {
console.log(v.x, v.y);
});
С точки зрения стиля кода pointer ничем не отличается от tween или spring — это тот же поток значений.
Это унификация источников данных, при которой взаимодействие пользователя становится частью анимационной системы.
Popmotion избегает концепции «полного перерендера состояния». Вместо этого обновляются только конкретные свойства.
boxStyler.set({
x: 100,
opacity: 0.5
});
Такой стиль делает обновления точечными, а не глобальными. Код становится ближе к описанию физических изменений, а не пересборке состояния.
Конфигурация анимации всегда передаётся через объект-литерал, но сама анимация остаётся функцией.
tween({
from: 50,
to: 250,
ease: 'easeInOut'
});
При этом отсутствует необходимость в создании экземпляров через
new. Это снижает когнитивную нагрузку и делает стиль
единообразным.
Анимации не запускаются автоматически. Запуск всегда явный, через
метод start. Это формирует предсказуемую модель
исполнения.
const animation = tween({
from: 0,
to: 100
});
animation.stop(); // управление полностью внешнее
Жизненный цикл разбивается на:
Без скрытых переходов между состояниями.
Popmotion поощряет ручную синхронизацию потоков вместо скрытых механизмов.
import { tween, spring } from 'popmotion';
const durationAnim = tween({ from: 0, to: 1, duration: 1000 });
const physicsAnim = spring({ from: 0, to: 300 });
durationAnim.start(v => {
physicsAnim.setVelocity(v * 10);
});
Здесь одна анимация управляет другой через явную передачу данных, что сохраняет прозрачность системы.
Функции, передаваемые в start, должны оставаться чистыми
по стилю: их задача — только принимать значение и применять его.
animation.start(v => {
element.style.transform = `translateX(${v}px)`;
});
Отсутствие дополнительной логики внутри update-обработчиков уменьшает связанность кода.
Easing-функции задаются декларативно, а не вычисляются вручную.
tween({
from: 0,
to: 400,
ease: 'easeOut'
});
Стиль кода предполагает, что поведение анимации описывается параметрами, а не императивной логикой.
Popmotion код структурируется так, чтобы побочные эффекты находились
только в одном месте — в подписке start.
const animation = tween({ from: 0, to: 1 });
animation.start(value => {
updateDOM(value);
});
Вся остальная часть системы не знает о DOM, событиях или рендеринге.
Popmotion избегает глобальных менеджеров анимации. Каждая анимация существует независимо, что формирует стиль:
const a = tween({ from: 0, to: 100 });
const b = spring({ from: 100, to: 200 });
Каждая сущность живёт в собственном контексте.
Все данные в Popmotion движутся в одном направлении:
конфигурация → анимация → поток значений → обработчик → эффект
Этот поток исключает обратные зависимости и упрощает анализ поведения системы во времени.
Popmotion хорошо ложится на модульную архитектуру, где каждая анимация оформляется как отдельная функция.
export const fadeIn = (element) =>
tween({ from: 0, to: 1 }).start(v => {
element.style.opacity = v;
});
Такой подход делает анимации переиспользуемыми без дополнительной абстракции классов или сервисов.
В коде отсутствует необходимость в классах, наследовании или методах объектов. Вся система строится вокруг функций и данных.
// отсутствует необходимость:
class Animation {}
// вместо этого:
const anim = tween({ from: 0, to: 100 });
Это снижает сложность и делает стиль более предсказуемым при масштабировании проекта.