Bounds и ограничивающие прямоугольники

В Paper.js объект Bounds представляет собой ограничивающий прямоугольник, который полностью охватывает другой объект, такой как Path, Raster, Group или Layer. Он задаётся через четыре основных свойства: x, y, width и height. Эти свойства описывают координаты левого верхнего угла прямоугольника и его размеры.

let path = new Path.Circle({
    center: [100, 100],
    radius: 50
});

console.log(path.bounds); // Bounds { x: 50, y: 50, width: 100, height: 100 }

Ключевой момент: bounds всегда возвращает прямоугольник, ориентированный по осям координат (axis-aligned), который охватывает объект полностью.


Свойства и методы Bounds

Свойства:

  • x, y — координаты верхнего левого угла.
  • width, height — размеры прямоугольника.
  • topLeft, topRight, bottomLeft, bottomRight — вершины прямоугольника.
  • center — центральная точка Bounds.
  • size — объект Size с шириной и высотой.
let rect = new Rectangle(new Point(50, 50), new Size(200, 100));

console.log(rect.topLeft);     // Point { x: 50, y: 50 }
console.log(rect.center);      // Point { x: 150, y: 100 }
console.log(rect.size.width);  // 200

Методы для работы с прямоугольниками:

  • contains(point) — проверяет, находится ли точка внутри Bounds.
  • intersects(bounds) — возвращает true, если два Bounds пересекаются.
  • expand(amount) — увеличивает размер Bounds на заданное значение.
  • include(point) — расширяет Bounds так, чтобы включить указанную точку.
let bounds = path.bounds;
bounds.expand(20); // Увеличивает ширину и высоту на 20 по каждой стороне

Различие между bounds, strokeBounds и handleBounds

Paper.js предоставляет несколько типов ограничивающих прямоугольников для одного объекта:

  1. bounds — охватывает только геометрию объекта без учета толщины контура (strokeWidth).
  2. strokeBounds — учитывает толщину линии (strokeWidth), полностью охватывая видимую часть объекта.
  3. handleBounds — включает в Bounds все контрольные точки кривых Безье (Bezier handles), что может быть важно при анимации и трансформации.
path.strokeWidth = 10;

console.log(path.bounds);        // Без учета толщины линии
console.log(path.strokeBounds);  // С учетом толщины линии
console.log(path.handleBounds);  // Включает управляющие точки

Важная деталь: при трансформациях, таких как вращение или масштабирование, handleBounds может значительно превышать bounds.


Использование Bounds для позиционирования и трансформации

Bounds позволяют точно позиционировать объекты относительно других объектов или канвы:

let rect = new Path.Rectangle([0, 0], [100, 50]);
let circle = new Path.Circle([0, 0], 25);

circle.position = rect.bounds.bottomRight;

В данном примере центр круга устанавливается в нижний правый угол прямоугольника.

Методы для работы с положением:

  • bounds.topLeft = point — перемещает объект так, чтобы его верхний левый угол совпал с точкой.
  • bounds.center = point — перемещает объект по центру.
rect.bounds.center = view.center; // Центрирует прямоугольник на канве

Операции над Bounds

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

  • Объединение Bounds:
let bounds1 = new Rectangle([0, 0], [50, 50]);
let bounds2 = new Rectangle([25, 25], [50, 50]);
let united = bounds1.unite(bounds2);

console.log(united); // Bounds { x: 0, y: 0, width: 75, height: 75 }
  • Пересечение Bounds:
let intersected = bounds1.intersect(bounds2);
console.log(intersected); // Bounds { x: 25, y: 25, width: 25, height: 25 }
  • Расширение или сжатие:
let expanded = bounds1.expand(10); // увеличивает по всем сторонам на 10
let contracted = bounds1.expand(-10); // уменьшает

Использование Bounds в динамических анимациях

Bounds позволяют легко реализовать коллизии, ограничения движения и адаптивное расположение:

function onFrame(event) {
    circle.position.x += 2;
    if (!view.bounds.contains(circle.bounds)) {
        circle.position.x = 0;
    }
}

В этом примере движение круга ограничено размерами канвы, используя view.bounds.


Интеграция с Group и Layer

Для Group и Layer Bounds вычисляются как объединение всех дочерних элементов:

let group = new Group([path1, path2, circle]);
console.log(group.bounds); // охватывает все объекты внутри группы

Практическая особенность: при добавлении или удалении объектов из группы, bounds автоматически пересчитываются.


Отличие Rectangle и Bounds

Rectangle — это статический объект, который можно использовать для создания Paths или вычислений. Bounds всегда привязаны к объекту Paper.js и обновляются автоматически при изменении формы объекта.

let rect = new Rectangle([0, 0], [100, 50]);
let path = new Path.Rectangle(rect);
console.log(path.bounds); // всегда соответствует текущей позиции и размеру Path

Вывод: использование Bounds обеспечивает точный контроль над позиционированием, коллизиями и трансформациями объектов в Paper.js, упрощая создание адаптивных и динамичных графических интерфейсов.