В системе анимации Velocity.js трансформации подчиняются не только порядку объявления свойств, но и фундаментальной модели композиции CSS-трансформаций, основанной на матричном умножении. Любое визуальное преобразование элемента в итоге сводится к построению итоговой матрицы transform, и именно порядок операций внутри этой матрицы определяет конечный результат.
Каждая трансформация в CSS (и, соответственно, в Velocity.js) представляется как матрица. При применении нескольких трансформаций они не складываются, а перемножаются.
Ключевая особенность:
Если заданы трансформации:
то итоговая матрица формируется как произведение:
M = T × R × S
Но визуально применяется справа налево:
Это означает, что «поздние» операции в записи оказываются «ближе» к объекту в пространстве преобразований.
В стандартной модели CSS:
transform: translate() rotate() scale();
фактическая последовательность вычислений:
Из этого следует важное поведение:
В Velocity.js трансформации могут задаваться двумя основными способами:
Velocity(element, {
transform: "translateX(100px) rotate(45deg) scale(1.5)"
});
В этом случае:
Итоговое поведение определяется браузером, а не библиотекой.
Velocity(element, {
translateX: 100,
rotateZ: 45,
scale: 1.5
});
Здесь появляется важная особенность:
Типичный порядок сборки:
Однако визуально это всё равно интерпретируется как матричное произведение, где итоговый эффект эквивалентен CSS-поведению.
Рассмотрим поведение на примерах.
Если задать:
translateX(100px) scale(2)
то результат будет отличаться от:
scale(2) translateX(100px)
Пояснение:
Итог:
Комбинация:
translateX(100px) rotate(90deg)
даёт:
Но:
rotate(90deg) translateX(100px)
даёт:
Это одно из самых частых источников неожиданных визуальных эффектов.
Порядок трансформаций тесно связан с точкой опоры:
Пример влияния:
transform-origin не меняет порядок операций, но меняет геометрию каждой из них.
При анимации transform в Velocity.js происходит несколько этапов:
На этапе сборки происходит ключевая фиксация порядка.
При одновременной анимации нескольких transform-свойств:
Например:
Velocity(element, {
translateX: 200,
rotateZ: 360
}, {
duration: 1000
});
Внутренне:
При последовательных вызовах:
Velocity(element, { translateX: 100 });
Velocity(element, { rotateZ: 45 });
поведение зависит от очереди:
Это важно, поскольку порядок не только внутри transform, но и между анимациями влияет на итоговую матрицу.
Критический момент:
Следствия:
Поэтому библиотека часто читает текущее состояние перед стартом анимации.
Основные закономерности:
Из этого вытекает:
В контексте Velocity.js корректнее рассматривать transform не как список операций, а как последовательность матричных преобразований:
Именно поэтому изменение порядка даже двух свойств полностью меняет поведение анимации без изменения числовых параметров.