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

В Paper.js каждое визуальное содержимое размещается в сцене (project), которая отображается на холсте <canvas>. Все объекты имеют свои координаты относительно пространства проекта, но при этом Paper.js использует локальные координаты элементов через их собственные трансформации.

Различие между пространствами критично для корректного управления положением, размером и вращением объектов. Основные виды пространств:

  • Глобальное пространство (global/project coordinates) – координаты относительно верхнего левого угла холста.
  • Локальное пространство объекта (local/object coordinates) – координаты внутри объекта, учитывающие его трансформации.
  • Экранное пространство (view coordinates) – координаты относительно видимой области окна браузера, полезны при обработке событий мыши.

Свойства и методы трансформации

Каждый объект Paper.js наследует свойства и методы для работы с преобразованиями:

  • position – центральная точка объекта в глобальном пространстве.
  • bounds – границы объекта в глобальных координатах.
  • matrix – объект Matrix, описывающий текущую трансформацию объекта.
  • applyMatrix – флаг, определяющий, будут ли трансформации записаны в вершины объекта или оставлены в матрице.
  • transform(matrix) – применение произвольной матрицы к объекту.

Матрицы трансформации

Matrix в Paper.js представляет собой аффинное преобразование с параметрами a, b, c, d, tx, ty, где:

[a  c  tx]
[b  d  ty]
[0  0   1]

Эта матрица описывает одновременно:

  • Масштабирование – параметры a и d.
  • Вращение и наклон (shear) – параметры b и c.
  • Смещение (translation) – параметры tx и ty.

Создание и применение матриц:

var matrix = new Matrix();
matrix.translate(100, 50);
matrix.rotate(45);
path.transform(matrix);

Методы translate(), rotate(), scale() вызываются на матрице и позволяют комбинировать несколько преобразований перед применением к объекту.


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

Paper.js предоставляет удобные методы для перевода координат из одного пространства в другое:

  • globalToLocal(point) – преобразует точку из глобального пространства в локальное объекта.
  • localToGlobal(point) – преобразует точку из локального пространства объекта в глобальное.
  • viewToProject(point) – перевод координаты мыши в координаты проекта.
  • projectToView(point) – обратное преобразование.

Пример:

var circle = new Path.Circle(new Point(150, 150), 50);
circle.rotate(30);

var localPoint = circle.globalToLocal(new Point(160, 160));
console.log(localPoint); // координата в системе круга

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


Вложенные объекты и группы

Группы (Group) в Paper.js создают иерархическое пространство:

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

Пример:

var group = new Group();
var rect = new Path.Rectangle([0, 0], [50, 50]);
var circle = new Path.Circle([100, 100], 25);
group.addChild(rect);
group.addChild(circle);

group.translate(new Point(50, 50));
console.log(rect.position); // позиция изменена относительно глобального пространства

Методы localToGlobal() и globalToLocal() применимы также к объектам внутри групп, учитывая трансформации родителей.


Работа с View и событиями мыши

View в Paper.js обеспечивает связь между координатами холста и координатами экрана:

  • event.point в обработчиках событий содержит точку в координатах View.
  • Для взаимодействия с объектами нужно переводить event.point в координаты проекта:
tool.onMouseD own = function(event) {
    var projectPoint = view.viewToProject(event.point);
    var hitResult = project.hitTest(projectPoint);
    if (hitResult) {
        hitResult.item.fillColor = 'red';
    }
};

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


Комбинирование преобразований

Часто требуется объединять несколько трансформаций:

  • Матрицы можно умножать, создавая сложные эффекты.
  • Применение нескольких методов translate, rotate, scale последовательно приводит к композиции аффинных преобразований.
  • Для обратного преобразования используется matrix.inverted(), что позволяет возвращать объекты и точки в исходное пространство.

Пример инверсии:

var matrix = new Matrix();
matrix.translate(100, 0);
matrix.rotate(45);

var inverted = matrix.inverted();
var originalPoint = inverted.transform(new Point(150, 50));

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

  • Всегда отслеживать, в каком пространстве находятся координаты, чтобы избежать ошибок при позиционировании и взаимодействии.
  • Для динамических объектов и анимаций использовать локальные координаты и матрицы, чтобы минимизировать пересчёт вершин.
  • При работе с группами трансформации на уровне группы проще и эффективнее, чем индивидуальные трансформации объектов.
  • Использование applyMatrix = true оптимизирует рендеринг для объектов с постоянными преобразованиями.

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