Matrix трансформации

Матрицы преобразований в браузерной графике лежат в основе всех операций перемещения, масштабирования и вращения элементов. Любая трансформация в CSS фактически сводится к применению аффинного преобразования, которое удобно представляется в виде матрицы. Такой подход позволяет объединять несколько операций в одну вычислительно эффективную структуру и передавать её в рендеринговый движок без необходимости пошаговой обработки каждого преобразования отдельно.

В двумерной графике каждый элемент описывается системой координат, в которой точка представляется вектором вида:

  • (x, y)

Любое преобразование изменяет положение этого вектора в пространстве. Базовые операции включают:

  • перенос (translation)
  • масштабирование (scale)
  • вращение (rotation)
  • наклон (skew)

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

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

Матрицы обеспечивают несколько ключевых свойств, критичных для браузерного рендеринга:

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

CSS трансформация, заданная через transform, в конечном итоге компилируется в матричное представление, даже если исходно использовались функции translate, rotate или scale.

Двумерная матрица transform

В двумерном пространстве используется аффинная матрица вида:

matrix(a, b, c, d, tx, ty)

Она соответствует матрице:

| a c tx |
| b d ty |
| 0 0  1 |

Каждый параметр отвечает за определённую часть преобразования:

  • a, d — масштаб по осям и компоненты вращения
  • b, c — элементы, отвечающие за наклон и синусоидальные компоненты вращения
  • tx, ty — смещение по осям X и Y

Применение этой матрицы к точке (x, y) выполняется через умножение векторов:

x' = ax + cy + tx
y' = bx + dy + ty

Преобразование базовых операций в матрицы

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

Перенос (translate)

matrix(1, 0, 0, 1, tx, ty)

Изменяются только компоненты смещения.

Масштабирование (scale)

matrix(sx, 0, 0, sy, 0, 0)

При равномерном масштабировании sx = sy.

Вращение (rotate)

matrix(cosθ, sinθ, -sinθ, cosθ, 0, 0)

Угловые компоненты распределяются между a, b, c, d, формируя поворот вектора в плоскости.

Наклон (skew)

matrix(1, tan(α), tan(β), 1, 0, 0)

Наклон изменяет взаимную ортогональность осей, создавая эффект сдвига.

Порядок умножения матриц

Композиция трансформаций определяется порядком умножения матриц. При последовательном применении операций:

transform = translate → rotate → scale

результирующая матрица вычисляется как:

M = T × R × S

Порядок критически влияет на итоговое положение объекта, поскольку матричное умножение некоммутативно.

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

Внутреннее представление transform в браузере

Современные браузеры преобразуют CSS transform в матрицы для последующей передачи в compositor thread. Даже если используется декларативный синтаксис:

transform: translateX(100px) rotate(45deg) scale(1.2)

внутри создаётся комбинированная матрица, которая затем применяется к элементу как единая операция.

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

  • минимизировать количество вычислений при перерисовке
  • использовать GPU для ускорения
  • избегать layout thrashing

Motion One и управление матрицами трансформаций

Библиотека Motion One работает поверх Web Animations API и абстрагирует работу с transform, предоставляя декларативный интерфейс для анимаций. Несмотря на высокоуровневый API, итоговые изменения всё равно приводят к модификации матриц.

Пример анимации:

import { animate } from "motion";

animate(
  element,
  {
    x: 200,
    rotate: 180,
    scale: 1.5
  },
  {
    duration: 1
  }
);

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

  • преобразует x в translateX
  • rotate в матрицу вращения
  • scale в масштабную матрицу
  • объединяет все компоненты в итоговую transform-матрицу

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

Интерполяция матриц

Анимация не выполняется путём линейного изменения отдельных параметров transform. Вместо этого происходит интерполяция компонентов матрицы.

Для каждого кадра вычисляется промежуточная матрица:

M(t) = M₀ + (M₁ - M₀) × t

где t — нормализованное время анимации.

Однако в реальных реализациях применяется более сложная модель, учитывающая:

  • разложение матрицы на translate/rotate/scale
  • корректную интерполяцию углов
  • избежание артефактов при вращении

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

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

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

Например:

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

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

Возможные проблемы:

  • конфликт порядка применения
  • накопление численных погрешностей
  • неожиданные траектории движения при одновременном вращении и переносе

3D матрица transform3d

Для трёхмерных преобразований используется матрица 4×4:

matrix3d(
  a1, b1, c1, d1,
  a2, b2, c2, d2,
  a3, b3, c3, d3,
  a4, b4, c4, d4
)

Она позволяет учитывать:

  • ось Z (глубина)
  • перспективу
  • проекционные искажения

В отличие от 2D матриц, здесь добавляется компонент глубины, что критично для вращений в пространстве и перспективных сцен.

Основные операции:

  • translate3d(x, y, z)
  • scale3d(x, y, z)
  • rotateX, rotateY, rotateZ

Все они преобразуются в 4×4 матрицы и умножаются в общем пространстве преобразований.

Связь Motion One и 3D трансформаций

При использовании 3D свойств Motion One выполняет ту же модель интерполяции, но расширенную до пространственных координат. Например:

animate(
  element,
  {
    rotateY: 180,
    translateZ: 100
  },
  {
    duration: 2
  }
);

Промежуточное состояние вычисляется через интерполяцию матриц 3D-пространства, что позволяет сохранять корректную перспективу при анимации.

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

Использование матриц напрямую связано с производительностью рендеринга:

  • трансформации выполняются на compositor thread
  • отсутствует влияние на layout при использовании transform
  • GPU ускоряет применение матриц
  • минимизируется repaint

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

Практические паттерны использования трансформаций

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

Централизованное управление transform

Все параметры состояния сводятся к одному источнику, который формирует итоговую матрицу:

  • позиция
  • масштаб
  • угол вращения

Изоляция осей

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

Кэширование состояний

Сохранение промежуточных матриц уменьшает количество пересчётов при повторных анимациях.

Избежание накопительных трансформаций

Прямое изменение transform без контроля базового состояния приводит к накоплению ошибок в матричном представлении, особенно при многократных анимациях.

Интерпретация transform как пространства состояний

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