Перерасчет координат

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


Координаты элементов

Каждый элемент Snap.svg имеет собственные координаты в локальной системе отсчета. Локальная система определяется:

  • Положением родительского контейнера (<svg> или группы <g>).
  • Любыми примененными трансформациями (transform), такими как translate, rotate, scale.

Для базового получения координат используется метод:

var bbox = element.getBBox();
console.log(bbox.x, bbox.y, bbox.width, bbox.height);

getBBox() возвращает ограничивающий прямоугольник элемента в текущей системе координат SVG, включая все трансформации.


Преобразование координат между системами

Если элемент вложен в группу, а группа имеет трансформации, координаты элемента локальные относительно группы, а не всего документа. Для преобразования в глобальные координаты используется метод getCTM() (Current Transformation Matrix):

var matrix = element.getCTM();
var globalX = matrix.e;
var globalY = matrix.f;

Эта матрица позволяет учитывать все трансформации: переносы, масштабирование и вращение. Она возвращает объект типа SVGMatrix:

  • a, b, c, d — элементы матрицы для масштабирования и вращения.
  • e, f — сдвиг по X и Y.

Для перерасчета любой точки (x, y) в глобальные координаты:

var pt = element.paper.createSVGPoint();
pt.x = x;
pt.y = y;
var globalPt = pt.matrixTransform(element.getCTM());

Применение трансформаций и пересчет координат

Snap.svg предоставляет метод transform(), который позволяет применить несколько операций одновременно:

element.transform('t100,50r45s2,2');
  • t100,50 — перенос (translate)
  • r45 — вращение (rotate)
  • s2,2 — масштабирование (scale)

Чтобы корректно пересчитать координаты после трансформации:

  1. Получить текущую матрицу: element.transform().globalMatrix
  2. Применить матрицу к исходной точке.
  3. При необходимости использовать метод inverse() для обратного преобразования из глобальных координат в локальные.

Пример обратного преобразования:

var invMatrix = element.getCTM().inverse();
var localPt = globalPt.matrixTransform(invMatrix);

Работа с вложенными группами

Элементы внутри <g> наследуют трансформации родителя. Для точного перерасчета:

  • Использовать element.getBBox() для локальных координат.
  • Использовать element.getCTM() для глобальных координат.
  • Для нескольких уровней вложенности применяются матрицы всех родительских групп, которые учитываются автоматически в getCTM().
var parentGroup = paper.group();
var rect = paper.rect(0, 0, 50, 50);
parentGroup.add(rect);
parentGroup.transform('t200,100r30');

var rectGlobal = rect.getCTM(); // учитывает трансформацию группы

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

  • Анимации: при анимации объекта необходимо пересчитывать координаты для точного позиционирования коллизий или выравнивания относительно других элементов.
rect.animate({transform: 't300,150'}, 1000, mina.easeinout, function() {
    var bbox = rect.getBBox();
    console.log('Новые координаты:', bbox.x, bbox.y);
});
  • Интерактивность: при обработке событий мыши координаты курсора могут требовать пересчета в локальные координаты элемента:
svg.addEventListener('mousemove', function(evt){
    var pt = svg.createSVGPoint();
    pt.x = evt.clientX;
    pt.y = evt.clientY;
    var local = pt.matrixTransform(svg.getScreenCTM().inverse());
    console.log('Локальные координаты курсора:', local.x, local.y);
});

Советы по оптимизации пересчета координат

  1. Минимизировать вызовы getBBox() при большом количестве элементов, так как это вычислительно затратная операция.
  2. Использовать предварительные матрицы для группы элементов, если трансформации одинаковы для всех объектов.
  3. Для часто обновляемых координат применять SVGPoint и matrixTransform, избегая повторного вычисления getCTM() для каждого события.
  4. Хранить исходные локальные координаты элемента для быстрого пересчета после любых трансформаций.

Особенности работы с кривыми и сложными фигурами

Для path-элементов перерасчет координат осуществляется через:

  • getBBox() — возвращает ограничивающий прямоугольник.
  • Методы Snap.svg для работы с точками пути: getPointAtLength(), getTotalLength().

Пример:

var path = paper.path("M10,10 C20,20, 40,20, 50,10");
var len = path.getTotalLength();
var pt = path.getPointAtLength(len/2); // точка в середине пути
var globalPt = pt.matrixTransform(path.getCTM());

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


Итоговые ключевые моменты

  • Локальные координаты: getBBox().
  • Глобальные координаты: getCTM() + matrixTransform().
  • Обратное преобразование: inverse().
  • Вложенные группы автоматически учитываются в getCTM().
  • Для динамических изменений использовать матрицы и точки для точного пересчета без постоянного вызова getBBox().

Перерасчет координат является фундаментальным инструментом для анимации, интерактивности и точного позиционирования в Snap.svg.