Матрица трансформации SVG – примеры кода

Матрица SVG-трансформации выражает перемещение, масштабирование, поворот и наклон как один transform matrix(a,b,c,d,e,f). Она полезна, когда несколько трансформаций нужно объединить, рассчитать или экспортировать из графического инструмента. Если вам нужно только простое перемещение, изменение размера или поворот, отдельные transform-функции из статьи SVG-трансформации обычно читать проще.

В этой статье вы узнаете, как:

  • читать шесть значений в matrix(a,b,c,d,e,f);
  • использовать значения матрицы для перемещения, масштабирования, поворота и наклона;
  • масштабировать или поворачивать объект вокруг выбранной опорной точки;
  • избегать частых ошибок с origin, порядком трансформаций и skew-значениями;
  • выбирать между читаемыми transform-функциями и рассчитанной матрицей.

Основы матрицы трансформации

Матрица SVG-трансформации – это матрица 3 x 3, которая объединяет перемещение, масштабирование, поворот и наклон. В SVG-синтаксисе matrix(a,b,c,d,e,f) записываются только первые шесть значений:

Матрица трансформации SVG 3 x 3

ПараметрТипичное использованиеSVG-обозначение
aКоэффициент масштабирования по оси X или значение косинуса угла поворотаsx / cos(α)
bКоэффициент наклона по оси Y или значение синуса угла поворотаtan(α) / sin(α)
cКоэффициент наклона по оси X или отрицательное значение синуса угла поворотаtan(α) / -sin(α)
dКоэффициент масштабирования по оси Y или значение косинуса угла поворотаsy / cos(α)
eПеремещение по оси Xtx
fПеремещение по оси Yty

Матрица преобразует точку (x prev, y prev) в (x new, y new):

Формула расчета координат через матрицу трансформации

SVG-элементы используют атрибут transform с синтаксисом матрицы. Вы передаете 6 значений в функцию матричной трансформации, чтобы задать перемещение, масштабирование, поворот и наклон:

transform="matrix(a,b,c,d,e,f)"

Как использовать матрицу SVG-трансформации

  1. Начните с единичной матрицы: matrix(1 0 0 1 0 0).
  2. Измените e и f, чтобы переместить элемент на tx и ty.
  3. Измените a и d, чтобы масштабировать по оси x и оси y.
  4. Используйте значения синуса и косинуса в a, b, c и d для поворота.
  5. Используйте b или c для наклона в зависимости от оси.
  6. Корректируйте e и f, когда масштабирование или поворот выполняются вокруг опорной точки, а не вокруг (0,0).

Матрица перемещения

Перемещение – это SVG-трансформация, которая сдвигает все точки объекта на одно и то же расстояние по параллельным линиям. Эта трансформация смещает начало системы координат элемента. Матрица перемещения выглядит так:

Формула матрицы перемещения

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

Матрица перемещения объединяет значения tx и ty, чтобы сдвинуть элемент по горизонтали и вертикали. Она перемещает объект на tx вдоль оси x и на ty вдоль оси y.

Рассмотрим пример с исходным синим кругом, который перемещается по оси x (красный), по оси y (оранжевый) и по обеим осям (зеленый):

 1<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
 2    <g fill="none">
 3        <!-- no translation -->
 4        <circle cx="15" cy="15" r="10" stroke="blue" /> 
 5        <!-- horizontal translation (tx = 30) -->
 6        <circle cx="15" cy="15" r="10" stroke="red" transform="matrix(1 0 0 1 30 0)" />
 7        <!-- vertical translation (ty = 25) -->
 8        <circle cx="15" cy="15" r="10" stroke="orange" transform="matrix(1 0 0 1 0 25)" />
 9        <!-- both horizontal and vertical translation (tx = 30, ty = 25) -->
10        <circle cx="15" cy="15" r="10" stroke="green" transform="matrix(1 0 0 1 30 25)" />
11    </g>
12</svg>

Действие атрибута transform="matrix(1,0,0,1,tx,ty)" означает изменение координат объекта по формулам:

x(new) = a·x(prev) + c·y(prev) + e = x(prev) + tx
y(new) = b·x(prev) + d·y(prev) + f = y(prev) + ty

В примере элемент <g> группирует круги, а fill="none" применяется ко всем кругам внутри группы. Изображение ниже показывает исходный круг и три перемещенные копии:

Четыре круга как пример матрицы перемещения

Матрица масштабирования

Масштабирование – это SVG-трансформация, которая увеличивает или уменьшает объект с помощью коэффициента масштаба. Матрица масштабирования используется для равномерного или неравномерного масштабирования объектов вдоль координатных осей. sx и sy – коэффициенты масштабирования для осей x и y. Если sx и sy больше 1, объект увеличивается; если они находятся между 0 и 1, объект уменьшается. Если коэффициенты различаются, объект масштабируется неравномерно, что дает эффект растяжения или сжатия. Матрица масштабирования выглядит так:

Формула матрицы масштабирования

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

Рассмотрим пример с исходным синим прямоугольником, который масштабируется равномерно и неравномерно относительно origin (0, 0) – рисунки a и b, а также равномерно масштабируется относительно точки (10, 10) – рисунок c:

 1<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
 2	<!-- uniform scale is shown in fig.a -->
 3	<g fill="none">
 4	    <rect x="10" y="10" width="20" height="20" stroke="blue" />  
 5		 <rect x="10" y="10" width="20" height="20" stroke="red" transform="matrix(1.5,0,0,1.5,0,0)" />
 6		 <rect x="10" y="10" width="20" height="20" stroke="orange" transform="matrix(2,0,0,2,0,0)" />
 7		 <rect x="10" y="10" width="20" height="20" stroke="green" transform="matrix(0.7,0,0,0.7,0,0)" />
 8	 </g>
 9	 <!-- non-uniform scale is shown in fig.b -->
10	 <g transform="translate(70)">
11		<rect x="10" y="10" width="20" height="20" fill="blue" />  
12		<rect x="10" y="10" width="20" height="20" fill="red" transform="matrix(1.5,0,0,2,0,0)" />
13		<rect x="10" y="10" width="20" height="20" fill="orange" transform="matrix(3,0,0,2.5,0,0)" />
14		<rect x="10" y="10" width="20" height="20" fill="green" transform="matrix(0.7,0,0,0.5,0,0)" />
15	 </g>
16	 <!-- uniform scale relative to point (10, 10) is shown in fig.c -->
17	 <g fill="none" transform="translate(170)">
18	    <rect x="10" y="10" width="20" height="20" stroke="blue" />
19	    <rect x="10" y="10" width="20" height="20" stroke="red" transform="matrix(1.5,0,0,1.5,-5,-5)" />
20	    <rect x="10" y="10" width="20" height="20" stroke="orange" transform="matrix(2,0,0,2,-10,-10)" />
21	    <rect x="10" y="10" width="20" height="20" stroke="green" transform="matrix(0.7,0,0,0.7,3,3)" />
22	 </g>
23</svg>

Результат выглядит так:

Четыре прямоугольника как пример матрицы масштабирования

Код выше использует матрицу масштабирования. Первая группа показывает равномерное масштабирование (рис. a), вторая – неравномерное масштабирование (рис. b), а третья – равномерное масштабирование вокруг точки (10, 10) (рис. c).

Примечание: Масштабирование выполняется относительно origin системы координат (0, 0). Если SVG-объект расположен не в origin, масштабирование может также сместить его видимое положение. Поэтому прямоугольники на рисунках a и b выглядят перемещенными.

Чтобы масштабировать вокруг конкретной опорной точки (cx, cy), нужно добавить к масштабируемой фигуре дополнительное перемещение, которое компенсирует сдвиг к этой точке (рис. c). Полная матрица трансформации, объединяющая перемещение и масштабирование:

matrix(sx,0,0,sy,cx·(1-sx),cy·(1-sy))

Эта матрица корректно масштабирует объект вокруг опорной точки (cx, cy) без нежелательного смещения. Коэффициенты cx·(1-sx) и cy·(1-sy) задают необходимое перемещение, чтобы объект сохранил исходное положение после масштабирования. Рассчитаем эти значения для красного прямоугольника (рис. c). Опорная точка (cx, cy) в этом примере равна (10, 10) – это левый верхний угол синего исходного прямоугольника:

cx·(1-sx)=10·(1-1.5)=10·(-0.5)=-5
cy·(1-sy)=10·(1-1.5)=10·(-0.5)=-5

Матрица поворота

Матрица поворота использует синус и косинус угла поворота:

Формула матрицы поворота

matrix(cos(α),sin(α),-sin(α),cos(α),0,0), где α – угол вокруг точки с координатами (0, 0) исходной системы координат.

Рассмотрим пример с исходным синим прямоугольником, повернутым на 90 градусов (зеленый), 180 градусов (серый), 270 градусов (бирюзовый), -45 градусов (красный) и 135 градусов (оранжевый):

 1<svg viewBox="-50 -50 200 200" xmlns="http://www.w3.org/2000/svg">
 2	<!-- rotation around point with coordinates (0, 0) is shown in fig.a -->
 3    <g>
 4	  <rect x="0" y="0" width="20" height="20" fill="blue" />
 5	  <rect x="0" y="0" width="20" height="20" fill="green" transform="matrix(0,1,-1,0,0,0)" />
 6	  <rect x="0" y="0" width="20" height="20" fill="grey" transform="matrix(-1,0,0,-1,0,0)" />
 7	  <rect x="0" y="0" width="20" height="20" fill="teal" transform="matrix(0,-1,1,0,0,0)" />
 8	  <rect x="0" y="0" width="20" height="20" fill="red" transform="matrix(0.7071,-0.7071,0.7071,0.7071,0,0)" />
 9	  <rect x="0" y="0" width="20" height="20" fill="orange" transform="matrix(-0.7071,0.7071,-0.7071,-0.7071,0,0)" />
10	<!-- rotation around point with coordinates (0, 0) is shown in fig.b -->
11    </g>
12	<g transform="translate(70)">
13	  <rect x="5" y="5" width="20" height="20" fill="blue" />
14	  <rect x="5" y="5" width="20" height="20" fill="green" transform="matrix(0,1,-1,0,0,0)" />
15	  <rect x="5" y="5" width="20" height="20" fill="grey" transform="matrix(-1,0,0,-1,0,0)" />
16	  <rect x="5" y="5" width="20" height="20" fill="teal" transform="matrix(0,-1,1,0,0,0)" />
17	  <rect x="5" y="5" width="20" height="20" fill="red" transform="matrix(0.7071,-0.7071,0.7071,0.7071,0,0)" />
18	  <rect x="5" y="5" width="20" height="20" fill="orange" transform="matrix(-0.7071,0.7071,-0.7071,-0.7071,0,0)" />
19	</g>
20    <!-- rotation around point with coordinates (5, 5) is shown in fig.c -->
21	<g transform="translate(140)">
22	  <rect x="5" y="5" width="20" height="20" fill="blue" />
23	  <rect x="5" y="5" width="20" height="20" fill="green" transform="matrix(0,1,-1,0,10,0)" />
24	  <rect x="5" y="5" width="20" height="20" fill="grey" transform="matrix(-1,0,0,-1,10,10)" />
25	  <rect x="5" y="5" width="20" height="20" fill="teal" transform="matrix(0,-1,1,0,0,10)" />
26	  <rect x="5" y="5" width="20" height="20" fill="red" transform="matrix(0.7071,-0.7071,0.7071,0.7071,-2,5)" />
27	  <rect x="5" y="5" width="20" height="20" fill="orange" transform="matrix(-0.7071,0.7071,-0.7071,-0.7071,12,5)" />
28	</g>
29</svg>

Примечание: При положительном значении угла поворот идет по часовой стрелке, а отрицательное значение дает поворот против часовой стрелки.

Результат SVG-поворота показан на рисунке:

Шесть прямоугольников как пример матрицы поворота

Примечание: Следующая матрица поворачивает объект вокруг опорной точки (cx, cy):

matrix(cos(α), sin(α), -sin(α), cos(α), cx·(1-cos(α))+cy·sin(α), cy·(1-cos(α))-cx·sin(α))

Коэффициенты cx·(1-cos(α))+cy·sin(α) и cy·(1-cos(α))-cx·sin(α) задают перемещение, необходимое для поворота вокруг опорной точки. Рассчитаем эти значения для красного прямоугольника (рис. c). Опорная точка (cx, cy) в этом примере равна (5, 5) – левый верхний угол синего исходного прямоугольника, а угол для красного прямоугольника равен -45°:

cos(-45°)=0.7071, sin(-45°)=-0.7071

cx·(1-cos(α))+cy·sin(α)=5·(1-0.7071)+5·(-0.7071)=-2
cy·(1-cos(α))-cx·sin(α)=5·(1-0.7071)-5·(-0.7071)=5

Матрица наклона

Наклон – это трансформация, которая поворачивает одну из осей системы координат элемента на определенный угол α по часовой стрелке или против нее. SVG-элементы можно наклонять с помощью матрицы наклона:

Формула матрицы наклона по оси x

matrix(1,0,tan(α),1,0,0) – эта матрица задает наклон вдоль оси x на угол α.

Формула матрицы наклона по оси y

matrix(1,tan(α),0,1,0,0) – эта матрица задает наклон вдоль оси y на угол α.

Ниже показан пример круга с трансформациями наклона:

 1<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
 2	<g fill="none">
 3		<circle cx="20" cy="20" r="10" stroke="blue" />
 4		<!-- skew transformation along the x-axis by α=45° -->
 5		<circle cx="20" cy="20" r="10" stroke="red" transform="matrix(1,0,1,1,0,0)" />
 6	</g>
 7	<g fill="none" transform="translate(70)">
 8		<circle cx="20" cy="20" r="10" stroke="blue" />
 9		<!-- skew transformation along the y-axis by α=45° -->
10		<circle cx="20" cy="20" r="10" stroke="orange" transform="matrix(1,1,0,1,0,0)" />
11	</g>
12</svg>

Отрисованный пример выглядит так:

Исходный круг и круг после применения матрицы наклона

Примечание: Угол α представляет наклон в градусах. Для матрицы наклона по оси x меняются координаты x, а координаты y остаются прежними. Для матрицы наклона по оси y меняются координаты y, а координаты x остаются прежними.

Типичные ошибки и исправления

ПроблемаПричинаРешение
Трансформация работает, но объект неожиданно смещаетсяТрансформации применяются относительно origin (0,0)Переместите объект к нужной опорной точке перед scale или rotation
Поворот происходит вокруг неправильной точкиМатрица поворота применена без компенсирующего перемещенияОбъедините перемещение, поворот и обратное перемещение в одной матрице
Масштабирование искажает положениеМасштабирование применено без корректировки значений перемещенияНастройте значения e и f или масштабируйте вокруг конкретной точки
Матрица не дает видимого эффектаЗначения матрицы неверны или равны единичной матрицеПроверьте, что значения отличаются от 1 0 0 1 0 0
Несколько transform переопределяют друг другаМатрица заменяет предыдущие операции transformОбъедините трансформации в одну матрицу или применяйте их в правильном порядке
Неожиданный наклонНеверные значения b или cУбедитесь, что skew-значения заданы намеренно и соответствуют нужному углу
Трансформации трудно отлаживатьЗначения матрицы сложно интерпретироватьНачните с простых трансформаций, например translate и scale, и усложняйте постепенно

Быстрые рецепты

Шпаргалка по матрице трансформации

ЦельМатрицаПримечания
Без трансформации, единичная матрицаmatrix(1 0 0 1 0 0)Сбрасывает все трансформации
Переместить на (tx, ty)matrix(1 0 0 1 tx ty)Перемещает объект без scale или rotation
Равномерно масштабировать на smatrix(s 0 0 s 0 0)Масштабирует относительно origin
Масштабировать на (sx, sy)matrix(sx 0 0 sy 0 0)Неравномерное масштабирование
Масштабировать вокруг точки (cx, cy)matrix(s 0 0 s cx*(1-s) cy*(1-s))Сохраняет опорную точку на месте
Повернуть на θ вокруг originmatrix(cosθ sinθ -sinθ cosθ 0 0)θ – угол, для которого рассчитаны sin и cos
Повернуть вокруг точки (cx, cy)matrix(cosθ sinθ -sinθ cosθ cx-cx*cosθ+cy*sinθ cy-cx*sinθ-cy*cosθ)Частый случай поворота
Наклонить по горизонтали на θmatrix(1 0 tanθ 1 0 0)Наклон вдоль оси x
Наклонить по вертикали на θmatrix(1 tanθ 0 1 0 0)Наклон вдоль оси y
Отразить по горизонталиmatrix(-1 0 0 1 w 0)w – ширина объекта
Отразить по вертикалиmatrix(1 0 0 -1 0 h)h – высота объекта
Объединить scale и rotationmatrix(a b c d e f)Предварительно рассчитайте объединенные значения

Шесть значений матрицы работают вместе как один transform и интерпретируются в текущей SVG-системе координат.

Практические SVG-примеры

Переместить объект на (tx, ty)

1<rect x="50" y="50" width="100" height="60" transform="matrix(1 0 0 1 40 30)" />

Масштабировать объект в 2 раза равномерно

1<rect x="50" y="50" width="80" height="40" transform="matrix(2 0 0 2 0 0)" />

Масштабировать объект вокруг его центра (cx, cy)

1<rect x="50" y="50" width="100" height="60" transform="matrix(2 0 0 2 -100 -80)" />

Перемещение компенсирует масштабирование вокруг центра.

Повернуть объект на 45 градусов вокруг origin

1<rect x="50" y="50" width="100" height="60" transform="matrix(0.707 0.707 -0.707 0.707 0 0)" />

Повернуть вокруг конкретной точки (cx, cy)

1<rect x="50" y="50" width="100" height="60" transform="matrix(0.707 0.707 -0.707 0.707 85 -35)" />

Применить горизонтальный наклон

1<rect x="40" y="40" width="120" height="60" transform="matrix(1 0 0.5 1 0 0)" />

Объединить перемещение, масштабирование и поворот

1<rect x="30" y="30" width="100" height="60" transform="matrix(1.5 0.5 -0.5 1.5 40 20)" />

FAQ – матрица SVG-трансформации

Что означает matrix(a,b,c,d,e,f) в SVG?

matrix(a,b,c,d,e,f) – это SVG transform-функция, которая хранит масштабирование, наклон, поворот и перемещение в шести значениях. Значения a, b, c и d влияют на scale, skew и rotation; значения e и f перемещают элемент.

Что такое единичная матрица в SVG?

Единичная матрица – это matrix(1 0 0 1 0 0). Она не меняет элемент и служит удобной отправной точкой, когда вы строите матрицу трансформации пошагово.

Почему matrix transform неожиданно перемещает объект?

Матричные трансформации применяются относительно origin текущей системы координат. Масштабирование или поворот объекта, расположенного не в (0,0), может изменить его видимое положение, если e и f не компенсируют опорную точку.

Что лучше использовать: matrix() или отдельные transform-функции?

Используйте отдельные функции translate(), scale() и rotate(), когда нужна читаемая SVG-разметка. Используйте matrix(), когда значения рассчитаны, экспортированы инструментом или должны объединить несколько трансформаций в один transform.

Спецификация и связанные ресурсы