Матрицы преобразований в браузерной графике лежат в основе всех операций перемещения, масштабирования и вращения элементов. Любая трансформация в CSS фактически сводится к применению аффинного преобразования, которое удобно представляется в виде матрицы. Такой подход позволяет объединять несколько операций в одну вычислительно эффективную структуру и передавать её в рендеринговый движок без необходимости пошаговой обработки каждого преобразования отдельно.
В двумерной графике каждый элемент описывается системой координат, в которой точка представляется вектором вида:
Любое преобразование изменяет положение этого вектора в пространстве. Базовые операции включают:
Вместо последовательного применения каждой операции используется единая матрица преобразования, которая агрегирует результат всех действий.
Матрицы обеспечивают несколько ключевых свойств, критичных для браузерного рендеринга:
CSS трансформация, заданная через transform, в конечном итоге компилируется в матричное представление, даже если исходно использовались функции translate, rotate или scale.
В двумерном пространстве используется аффинная матрица вида:
matrix(a, b, c, d, tx, ty)
Она соответствует матрице:
| a c tx |
| b d ty |
| 0 0 1 |
Каждый параметр отвечает за определённую часть преобразования:
Применение этой матрицы к точке (x, y) выполняется через умножение векторов:
x' = ax + cy + tx
y' = bx + dy + ty
Каждая базовая операция может быть представлена через матричную форму.
matrix(1, 0, 0, 1, tx, ty)
Изменяются только компоненты смещения.
matrix(sx, 0, 0, sy, 0, 0)
При равномерном масштабировании sx = sy.
matrix(cosθ, sinθ, -sinθ, cosθ, 0, 0)
Угловые компоненты распределяются между a, b, c, d, формируя поворот вектора в плоскости.
matrix(1, tan(α), tan(β), 1, 0, 0)
Наклон изменяет взаимную ортогональность осей, создавая эффект сдвига.
Композиция трансформаций определяется порядком умножения матриц. При последовательном применении операций:
transform = translate → rotate → scale
результирующая матрица вычисляется как:
M = T × R × S
Порядок критически влияет на итоговое положение объекта, поскольку матричное умножение некоммутативно.
Изменение порядка операций приводит к различным результатам даже при одинаковых параметрах преобразований.
Современные браузеры преобразуют CSS transform в матрицы для последующей передачи в compositor thread. Даже если используется декларативный синтаксис:
transform: translateX(100px) rotate(45deg) scale(1.2)
внутри создаётся комбинированная матрица, которая затем применяется к элементу как единая операция.
Это позволяет:
Библиотека Motion One работает поверх Web Animations API и абстрагирует работу с transform, предоставляя декларативный интерфейс для анимаций. Несмотря на высокоуровневый API, итоговые изменения всё равно приводят к модификации матриц.
Пример анимации:
import { animate } from "motion";
animate(
element,
{
x: 200,
rotate: 180,
scale: 1.5
},
{
duration: 1
}
);
В этом случае Motion One:
Фактически происходит постепенная интерполяция между двумя матрицами состояния: начальной и конечной.
Анимация не выполняется путём линейного изменения отдельных параметров transform. Вместо этого происходит интерполяция компонентов матрицы.
Для каждого кадра вычисляется промежуточная матрица:
M(t) = M₀ + (M₁ - M₀) × t
где t — нормализованное время анимации.
Однако в реальных реализациях применяется более сложная модель, учитывающая:
Motion One использует декомпозицию трансформаций для обеспечения стабильного поведения анимации при сложных комбинациях свойств.
При одновременном изменении нескольких свойств трансформации происходит последовательное объединение промежуточных матриц.
Например:
animate(element, { x: 100 });
animate(element, { rotate: 90 });
Каждая анимация формирует собственную матрицу, а итоговое состояние определяется композицией этих преобразований.
Возможные проблемы:
Для трёхмерных преобразований используется матрица 4×4:
matrix3d(
a1, b1, c1, d1,
a2, b2, c2, d2,
a3, b3, c3, d3,
a4, b4, c4, d4
)
Она позволяет учитывать:
В отличие от 2D матриц, здесь добавляется компонент глубины, что критично для вращений в пространстве и перспективных сцен.
Основные операции:
Все они преобразуются в 4×4 матрицы и умножаются в общем пространстве преобразований.
При использовании 3D свойств Motion One выполняет ту же модель интерполяции, но расширенную до пространственных координат. Например:
animate(
element,
{
rotateY: 180,
translateZ: 100
},
{
duration: 2
}
);
Промежуточное состояние вычисляется через интерполяцию матриц 3D-пространства, что позволяет сохранять корректную перспективу при анимации.
Использование матриц напрямую связано с производительностью рендеринга:
Критическим фактором является количество операций умножения матриц. Чем меньше отдельных transform-операций, тем быстрее вычисляется итоговая матрица.
Композиция трансформаций в Motion One часто строится вокруг нескольких устойчивых моделей:
Все параметры состояния сводятся к одному источнику, который формирует итоговую матрицу:
Разделение анимаций по независимым осям позволяет избежать конфликтов матричного умножения.
Сохранение промежуточных матриц уменьшает количество пересчётов при повторных анимациях.
Прямое изменение transform без контроля базового состояния приводит к накоплению ошибок в матричном представлении, особенно при многократных анимациях.
Каждый элемент в DOM можно рассматривать как точку в многомерном пространстве состояний, где матрица определяет его положение и ориентацию. Motion One управляет переходами между этими состояниями, сводя сложные цепочки трансформаций к непрерывной интерполяции матриц, обеспечивающей плавность и согласованность визуального результата.