Popmotion опирается на концепцию императивного управления стилями
через обёртку над DOM-элементами. Вместо прямого изменения
element.style используется слой абстракции, который
позволяет единообразно работать с анимациями, преобразованиями и
единицами измерения.
Ключевая сущность — styler. Она создаёт объект,
инкапсулирующий доступ к стилям элемента и обеспечивающий их реактивное
обновление.
import { styler } from 'popmotion';
const box = document.querySelector('.box');
const boxStyler = styler(box);
boxStyler.set({
x: 0,
opacity: 1
});
styler позволяет работать не только с CSS-свойствами, но
и с абстрактными значениями вроде x, scale,
rotate. Эти свойства автоматически транслируются в
соответствующие CSS transform-значения.
Popmotion разделяет стили на две категории:
opacity,
backgroundColor, width)x, y,
scale, rotate, skew)Transform-свойства агрегируются в единую строку
transform, что позволяет избежать конфликтов между
отдельными трансформациями.
boxStyler.set({
x: 100,
y: 50,
rotate: 45
});
Результат будет преобразован в:
transform: translateX(100px) translateY(50px) rotate(45deg);
Такой подход устраняет необходимость ручного управления порядком трансформаций и снижает вероятность ошибок при комбинировании эффектов.
Внутри Popmotion transform реализован как набор чистых функций, которые преобразуют числовые значения в корректные CSS-строки. Это обеспечивает предсказуемость и возможность композиции.
Основные типы преобразований:
boxStyler.set({
rotate: 180
});
Значение автоматически интерпретируется как 180deg, без
необходимости явного указания единиц измерения.
Свойства x и y в Popmotion не являются
прямыми CSS-свойствами. Они представляют собой синтетические
трансформации, основанные на translateX и
translateY.
boxStyler.set({
x: 200,
y: 100
});
Внутренне это преобразуется в:
transform: translateX(200px) translateY(100px);
Использование x и y предпочтительнее
прямого transform, так как Popmotion сохраняет контроль над
порядком и совместимостью всех трансформаций.
Свойства scale и rotate интегрированы в
единую систему трансформаций.
boxStyler.set({
scale: 1.5,
rotate: 90
});
Композиция выполняется автоматически:
transform: scale(1.5) rotate(90deg);
Popmotion сохраняет внутренний порядок применения трансформаций, что важно для визуальной консистентности. Изменение порядка операций вручную часто приводит к другим визуальным результатам, особенно при сочетании вращения и смещения.
Одной из ключевых возможностей является интерполяция между
состояниями. Popmotion использует систему transform-утилит,
которые позволяют плавно переходить между значениями.
import { tween } from 'popmotion';
tween({
from: { x: 0, scale: 1 },
to: { x: 300, scale: 2 }
}).start(v => {
boxStyler.set(v);
});
Значения x и scale интерполируются
независимо, но применяются в одном обновлении стилей.
Popmotion автоматически управляет единицами измерения:
x, y → pxrotate → degscale → без единицЭто устраняет необходимость ручного управления строковыми значениями CSS.
boxStyler.set({
x: 10, // 10px
rotate: 45, // 45deg
opacity: 0.5
});
Popmotion использует функциональный подход к преобразованиям. Каждое изменение можно рассматривать как функцию, которая преобразует входное значение.
Внутри библиотеки используется идея композиции:
Это позволяет строить сложные цепочки трансформаций без потери контроля над отдельными компонентами.
Механизм pipe позволяет соединять несколько
преобразований в одну цепочку. Это особенно важно при работе с
динамическими значениями, поступающими из анимаций.
import { pipe, clamp } from 'popmotion';
const transformValue = pipe(
v => v * 2,
clamp(0, 100)
);
Такие функции часто применяются к координатам или масштабам перед
передачей в styler.
keyframes позволяют задавать промежуточные состояния
стилей, включая transform-свойства.
import { keyframes } from 'popmotion';
keyframes({
values: [
{ x: 0, rotate: 0 },
{ x: 150, rotate: 180 },
{ x: 300, rotate: 360 }
],
duration: 2000
}).start(v => {
boxStyler.set(v);
});
Каждый кадр интерполируется, создавая непрерывное движение. Transform-свойства комбинируются автоматически, без ручного расчёта промежуточных значений.
Spring-модель применяется ко всем transform-свойствам одинаково, обеспечивая естественную динамику движения.
import { spring } from 'popmotion';
spring({
from: { x: 0 },
to: { x: 300 }
}).start(v => {
boxStyler.set(v);
});
Поведение зависит от параметров физической модели:
Transform-свойства в этом случае ведут себя как координаты физической системы.
Порядок имеет значение при комбинировании нескольких трансформаций. Popmotion фиксирует внутреннюю последовательность:
Эта последовательность обеспечивает предсказуемое визуальное поведение независимо от порядка объявления в объекте.
boxStyler.set({
scale: 2,
x: 100,
rotate: 45
});
Результат всегда будет приведён к единой структуре transform.
Transform-свойства оптимизированы для работы с GPU через CSS. Popmotion старается минимизировать:
Использование transform и opacity позволяет
задействовать композитный слой браузера, что делает анимации более
плавными.
При частых обновлениях Popmotion объединяет изменения в один кадр анимации. Это снижает нагрузку на браузер.
boxStyler.set({ x: 10 });
boxStyler.set({ x: 20 });
boxStyler.set({ x: 30 });
Фактически применено будет только последнее значение в рамках одного кадра.
Popmotion не заменяет CSS, а расширяет его модель. Любые значения могут сосуществовать:
boxStyler.set({
x: 100,
opacity: 0.8
});
При этом обычные CSS-свойства продолжают применяться через стандартный механизм, а transform-свойства агрегируются отдельно.
Свойства x, y, scale,
rotate являются синтетическими. Они не существуют в CSS
напрямую, но предоставляются Popmotion как удобный API.
Это позволяет:
Transform-система тесно связана с потоками данных. Любое значение может быть источником анимации:
Popmotion преобразует эти источники в единый формат, пригодный для
применения к стилям через styler.
Popmotion поддерживает частичные обновления, при которых изменяется только одно свойство трансформации без влияния на остальные.
boxStyler.set({ x: 100 });
boxStyler.set({ rotate: 45 });
Каждое обновление сохраняет предыдущее состояние других transform-компонентов, что исключает конфликт между ними.