Стили и трансформации

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-значения.


Внутреннее представление transform-свойств

Popmotion разделяет стили на две категории:

  • обычные CSS-свойства (opacity, backgroundColor, width)
  • transform-свойства (x, y, scale, rotate, skew)

Transform-свойства агрегируются в единую строку transform, что позволяет избежать конфликтов между отдельными трансформациями.

boxStyler.set({
  x: 100,
  y: 50,
  rotate: 45
});

Результат будет преобразован в:

transform: translateX(100px) translateY(50px) rotate(45deg);

Такой подход устраняет необходимость ручного управления порядком трансформаций и снижает вероятность ошибок при комбинировании эффектов.


Абстракция transform-системы

Внутри Popmotion transform реализован как набор чистых функций, которые преобразуют числовые значения в корректные CSS-строки. Это обеспечивает предсказуемость и возможность композиции.

Основные типы преобразований:

  • перевод чисел в пиксели
  • перевод углов в градусы
  • нормализация значений диапазона
  • объединение нескольких трансформаций в одну строку
boxStyler.set({
  rotate: 180
});

Значение автоматически интерпретируется как 180deg, без необходимости явного указания единиц измерения.


Работа с координатами x и y

Свойства 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 сохраняет внутренний порядок применения трансформаций, что важно для визуальной консистентности. Изменение порядка операций вручную часто приводит к другим визуальным результатам, особенно при сочетании вращения и смещения.


Интерполяция значений transform

Одной из ключевых возможностей является интерполяция между состояниями. 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, ypx
  • rotatedeg
  • scale → без единиц
  • opacity → числовое значение без единиц

Это устраняет необходимость ручного управления строковыми значениями CSS.

boxStyler.set({
  x: 10,      // 10px
  rotate: 45, // 45deg
  opacity: 0.5
});

Композиция transform-функций

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

Внутри библиотеки используется идея композиции:

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

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


Пайпинг значений и transform-потоки

Механизм 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-анимации и физическая модель трансформаций

Spring-модель применяется ко всем transform-свойствам одинаково, обеспечивая естественную динамику движения.

import { spring } from 'popmotion';

spring({
  from: { x: 0 },
  to: { x: 300 }
}).start(v => {
  boxStyler.set(v);
});

Поведение зависит от параметров физической модели:

  • stiffness — жёсткость пружины
  • damping — затухание
  • mass — масса объекта

Transform-свойства в этом случае ведут себя как координаты физической системы.


Последовательность применения transform-свойств

Порядок имеет значение при комбинировании нескольких трансформаций. Popmotion фиксирует внутреннюю последовательность:

  1. translate (x, y)
  2. rotate
  3. scale
  4. skew

Эта последовательность обеспечивает предсказуемое визуальное поведение независимо от порядка объявления в объекте.

boxStyler.set({
  scale: 2,
  x: 100,
  rotate: 45
});

Результат всегда будет приведён к единой структуре transform.


Производительность трансформаций

Transform-свойства оптимизированы для работы с GPU через CSS. Popmotion старается минимизировать:

  • перерасчёт layout
  • вызовы reflow
  • избыточные обновления DOM

Использование transform и opacity позволяет задействовать композитный слой браузера, что делает анимации более плавными.


Агрегация стилей и батчинг обновлений

При частых обновлениях Popmotion объединяет изменения в один кадр анимации. Это снижает нагрузку на браузер.

boxStyler.set({ x: 10 });
boxStyler.set({ x: 20 });
boxStyler.set({ x: 30 });

Фактически применено будет только последнее значение в рамках одного кадра.


Совместимость transform-системы с CSS

Popmotion не заменяет CSS, а расширяет его модель. Любые значения могут сосуществовать:

boxStyler.set({
  x: 100,
  opacity: 0.8
});

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


Синтетические свойства и их роль

Свойства x, y, scale, rotate являются синтетическими. Они не существуют в CSS напрямую, но предоставляются Popmotion как удобный API.

Это позволяет:

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

Связь transform и потоков значений

Transform-система тесно связана с потоками данных. Любое значение может быть источником анимации:

  • пользовательский ввод
  • события мыши
  • скролл
  • таймеры
  • физические модели

Popmotion преобразует эти источники в единый формат, пригодный для применения к стилям через styler.


Инкрементальные изменения transform

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

boxStyler.set({ x: 100 });
boxStyler.set({ rotate: 45 });

Каждое обновление сохраняет предыдущее состояние других transform-компонентов, что исключает конфликт между ними.