Матричные преобразования

Матричные преобразования позволяют управлять положением, масштабом, поворотом и искажением графических объектов с помощью единого математического инструмента — матрицы трансформации. В SVG.js каждое графическое примитивное или сложное SVG-объектное представление поддерживает работу с матрицами через методы transform(), matrix() и встроенные трансформации translate, rotate, scale, skew.


Представление матрицы

Матрица 2D-трансформации обычно имеет вид:

[a, c, e]
[b, d, f]

где:

  • a и d — коэффициенты масштабирования по осям X и Y,
  • b и c — коэффициенты наклона (shear),
  • e и f — смещения по X и Y (translate).

В SVG.js матрица представляется объектом SVG.Matrix с методами для сложения, умножения и применения к элементам:

let m = new SVG.Matrix(1, 0, 0, 1, 0, 0); // Единичная матрица

Применение матрицы к элементу

Для применения матрицы к объекту используется метод transform():

let rect = draw.rect(100, 50).fill('#f06');
let m = new SVG.Matrix().translate(50, 100).rotate(45);
rect.transform({ matrix: m });

Здесь сначала создается матрица с последовательными преобразованиями — смещение на (50, 100) и поворот на 45°. Метод transform({ matrix }) заменяет текущую трансформацию объекта на указанную матрицу.


Последовательные преобразования

Важное правило: порядок операций матричного преобразования влияет на результат. В SVG.js операции применяются последовательно, начиная с единичной матрицы:

let m = new SVG.Matrix();
m = m.translate(100, 50); // Сначала смещение
m = m.rotate(30);          // Потом поворот
m = m.scale(2, 1.5);       // Потом масштабирование
rect.transform({ matrix: m });

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


Основные методы класса SVG.Matrix

  • translate(x, y) — смещает объект на x и y.
  • scale(sx, sy, cx, cy) — масштабирует объект относительно точки (cx, cy). Если sy не указан, используется значение sx.
  • rotate(angle, cx, cy) — поворачивает объект на угол angle вокруг точки (cx, cy). Если центр не указан, поворот происходит вокруг (0,0).
  • skewX(angle) и skewY(angle) — наклон по осям.
  • flip() — зеркальное отображение по горизонтали или вертикали.
  • multiply(matrix) — умножение текущей матрицы на другую, полезно для объединения нескольких трансформаций.
  • clone() — создает копию матрицы для безопасных вычислений.

Пример комбинирования матриц:

let m1 = new SVG.Matrix().translate(50, 50);
let m2 = new SVG.Matrix().rotate(45);
let m3 = m1.multiply(m2);
rect.transform({ matrix: m3 });

Применение к сложным элементам

Группы (SVG.Group) поддерживают наследование матриц от родительского элемента. Любое преобразование, применяемое к группе, влияет на все дочерние элементы:

let group = draw.group();
group.add(draw.circle(40).fill('#0f0').move(10, 10));
group.add(draw.rect(60, 30).fill('#00f').move(50, 50));
group.transform({ matrix: new SVG.Matrix().rotate(30) });

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


Получение текущей матрицы элемента

Метод matrix() возвращает текущую матрицу трансформации объекта, которую можно использовать для вычислений:

let currentMatrix = rect.matrix();
console.log(currentMatrix.a, currentMatrix.b, currentMatrix.c, currentMatrix.d, currentMatrix.e, currentMatrix.f);

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


Прямое управление через атрибут transform

SVG.js позволяет напрямую задавать атрибут transform через строку, но использование SVG.Matrix предпочтительнее, так как обеспечивает точные вычисления и удобные методы объединения:

rect.attr('transform', 'matrix(1,0,0,1,50,100)'); // Альтернатива

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

  1. Анимация сложных трансформаций:
rect.animate(1000, '<>').transform({
  matrix: new SVG.Matrix().translate(200, 0).rotate(90)
});
  1. Композиция трансформаций:
let m = new SVG.Matrix().scale(1.5).rotate(45).translate(30, 20);
rect.transform({ matrix: m });
  1. Интерактивное управление положением объектов:

При перетаскивании можно обновлять матрицу объекта:

rect.on('dragmove', e => {
  let dx = e.detail.p.x;
  let dy = e.detail.p.y;
  rect.transform({ matrix: new SVG.Matrix().translate(dx, dy) });
});

Вывод

Матричные преобразования в SVG.js обеспечивают мощный и гибкий инструмент для работы с графикой. Понимание структуры матрицы, порядка применения операций и возможностей класса SVG.Matrix позволяет создавать сложные композиции, анимации и интерактивные элементы с высокой точностью.