Порядок применения трансформаций

В CSS и в системах анимации на основе матриц трансформации ключевым фактором является не только набор используемых операций, но и строгая последовательность их применения. В Motion One трансформации формируются в виде единой строки transform, которая затем интерпретируется браузером как последовательность матричных преобразований. При этом итоговый визуальный результат определяется порядком операций, а не только их значениями.


Математическая природа порядка трансформаций

Любая трансформация в двумерной или трёхмерной системе координат может быть представлена как матрица. При комбинировании нескольких операций происходит перемножение матриц, где важен порядок:

  • умножение матриц не коммутативно;
  • изменение порядка операций меняет итоговую систему координат элемента;
  • каждая последующая операция применяется к уже преобразованной системе.

В терминах CSS это означает, что выражение:

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

даёт иной результат, чем:

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

В первом случае элемент сначала сдвигается по оси X, а затем поворачивается вокруг уже смещённой позиции. Во втором — сначала вращается вокруг центра, а затем смещается по уже повернутой системе координат.


Как Motion One формирует transform

Motion One не хранит трансформации как готовую строку. Вместо этого каждая трансформация задаётся как отдельное свойство:

import { animate } from "motion";

animate(element, {
  x: 100,
  rotate: 45,
  scale: 1.2
});

На этапе рендеринга библиотека собирает итоговую строку transform, комбинируя значения в заранее определённом порядке.


Внутренний порядок объединения трансформаций

Motion One использует фиксированную последовательность, близкую к стандартной модели браузеров:

  1. translate (x, y, z)
  2. rotate (rotate, rotateX, rotateY, rotateZ)
  3. scale (scale, scaleX, scaleY)
  4. skew (skewX, skewY)
  5. additional transforms (matrix, perspective при наличии)

Формирование строки происходит не в порядке объявления свойств, а согласно внутреннему шаблону преобразований.

Пример:

animate(element, {
  scale: 1.5,
  x: 200,
  rotate: 90
});

Фактический результат будет эквивалентен:

transform: translateX(200px) rotate(90deg) scale(1.5);

Даже если свойства заданы в другом порядке, итоговая строка формируется по внутреннему правилу композиции.


Почему порядок фиксирован

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

Если бы порядок зависел от объявления, возникали бы проблемы:

  • различие анимации между кадрами при динамическом добавлении свойств;
  • невозможность корректной интерполяции матриц;
  • скачки при переходах между состояниями.

Единый порядок позволяет Motion One:

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

Интерполяция и влияние порядка

При анимации Motion One преобразует начальные и конечные значения в промежуточные матрицы. Рассмотрим:

animate(element, {
  x: 0,
  rotate: 0
});

animate(element, {
  x: 300,
  rotate: 180
});

Если порядок был бы различным в разных состояниях, например:

  • состояние A: translate → rotate
  • состояние B: rotate → translate

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

Motion One предотвращает это, нормализуя порядок до единой схемы.


Transform order и визуальные артефакты

Порядок трансформаций напрямую влияет на геометрию движения элемента.

Перемещение до вращения

animate(element, {
  x: 200,
  rotate: 45
});

Результат:

  • элемент смещается по оси X
  • затем поворачивается вокруг смещённой точки
  • траектория движения описывает дугу

Вращение до перемещения

При обратной логике:

transform: rotate(45deg) translateX(200px);
  • элемент сначала вращается вокруг центра
  • затем смещается по повернутой оси X
  • траектория становится наклонённой относительно исходной системы координат

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


Смешивание независимых трансформаций

Motion One позволяет одновременно анимировать несколько независимых свойств:

animate(element, {
  x: 100,
  y: 50,
  rotateZ: 30,
  scale: 2
});

Внутри происходит объединение:

  • translate формируется из x и y
  • rotateZ добавляется в блок вращений
  • scale применяется после вращения и переноса

Итоговая строка всегда соответствует внутреннему шаблону:

transform: translate(100px, 50px) rotateZ(30deg) scale(2);

Конфликты при ручном задании transform

При одновременном использовании style.transform и Motion One возникает конкуренция за управление строкой трансформации.

element.style.transform = "rotate(10deg)";

animate(element, {
  x: 100
});

В этом случае Motion One может:

  • перезаписать transform;
  • объединить текущее значение через чтение computed style;
  • нормализовать порядок, игнорируя исходную строку.

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


transformTemplate и контроль композиции

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

animate(
  element,
  { x: 100, rotate: 45 },
  {
    transformTemplate: ({ x, rotate }) =>
      `rotate(${rotate}) translateX(${x}px)`
  }
);

В этом случае порядок становится явным и переопределяет стандартную схему.

Использование шаблона изменяет ключевое свойство системы:

  • интерполяция выполняется по заданной строке;
  • Motion One перестаёт автоматически перестраивать порядок;
  • ответственность за корректность композиции переносится на разработчика.

Связь порядка трансформаций и системы координат

Каждая операция трансформации изменяет локальную систему координат элемента:

  • translate смещает начало координат;
  • rotate изменяет ориентацию осей;
  • scale изменяет единичные расстояния.

Таким образом, порядок операций фактически определяет, в какой системе координат выполняется следующая операция.

Motion One всегда строит цепочку так, чтобы:

  • translate задавал базовое смещение;
  • rotate применялся в уже смещённой системе;
  • scale завершал преобразование, не влияя на направление осей.

Композиция нескольких анимаций

При наложении нескольких animate() на один элемент порядок трансформаций не дублируется, а объединяется:

animate(element, { x: 100 });
animate(element, { rotate: 45 });

Система:

  • сливает трансформации в единый набор;
  • пересобирает строку transform;
  • применяет единый порядок независимо от очередности вызовов.

Это предотвращает появление конфликтующих цепочек трансформаций.


Итоговая модель порядка в Motion One

Поведение системы можно свести к нескольким ключевым принципам:

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

Эта модель обеспечивает предсказуемость анимации даже при сложных комбинациях перемещений, вращений и масштабирования, сохраняя единое пространство преобразований для всех состояний элемента.