StrokeBounds

В библиотеке Paper.js объект Path и другие графические элементы имеют два типа границ: bounds и strokeBounds. Если bounds описывает прямоугольник, полностью охватывающий геометрию фигуры без учета толщины линии, то strokeBounds учитывает толщину контура (strokeWidth) и обеспечивает точное описание области, которую фактически занимает фигура на холсте.


Основное свойство strokeBounds

Каждый объект Paper.js, который наследует от Item и имеет визуальное представление (например, Path, Shape, Raster), поддерживает свойство:

item.strokeBounds
  • Тип: Rectangle
  • Описание: возвращает прямоугольник, включающий контур фигуры с толщиной линии.
  • Отличие от bounds: bounds игнорирует strokeWidth, поэтому при визуализации фигуры с толстой линией реальный занимаемый объем будет больше, чем у bounds.

Пример:

var path = new Path.Circle({
    center: [50, 50],
    radius: 30,
    strokeColor: 'black',
    strokeWidth: 10
});

console.log('bounds:', path.bounds);           // Rectangle без учёта толщины
console.log('strokeBounds:', path.strokeBounds); // Rectangle с учётом толщины линии

В этом случае strokeBounds расширяется на 5 пикселей с каждой стороны, так как strokeWidth = 10.


Использование strokeBounds для выравнивания

strokeBounds особенно полезно при автоматическом позиционировании объектов:

var rect = new Path.Rectangle({
    point: [0, 0],
    size: [80, 40],
    strokeColor: 'blue',
    strokeWidth: 20
});

rect.position = view.center;

// Выравнивание по правому краю с учётом толщины линии
rect.bounds.right = view.bounds.right;

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


Методы и свойства Rectangle для работы с strokeBounds

strokeBounds возвращает объект типа Rectangle, который имеет все стандартные свойства:

  • width и height – размеры с учётом толщины линии.
  • topLeft, bottomRight, center – ключевые точки прямоугольника.
  • contains(point) – проверка, находится ли точка внутри прямоугольника.
  • intersects(rect) – проверка пересечения с другим прямоугольником.

Пример проверки пересечения:

var circle = new Path.Circle({
    center: [100, 100],
    radius: 50,
    strokeColor: 'red',
    strokeWidth: 15
});

var rect = new Path.Rectangle({
    point: [120, 120],
    size: [80, 80],
    strokeColor: 'green',
    strokeWidth: 5
});

if (circle.strokeBounds.intersects(rect.strokeBounds)) {
    console.log('Объекты пересекаются с учетом толщины линий');
}

Отличие от bounds при кривых и сложных фигурах

Для кривых Безье (Path.Curve) или многоугольников strokeBounds корректно учитывает:

  • Все контрольные точки кривой.
  • Толщину линии, включая митры и концевые заглушки (strokeCap и strokeJoin).

Пример:

var path = new Path();
path.add(new Point(50, 50));
path.add(new Point(150, 50));
path.add(new Point(150, 150));
path.strokeColor = 'black';
path.strokeWidth = 20;
path.strokeJoin = 'round';

console.log('bounds:', path.bounds);             // Минимальный прямоугольник по точкам
console.log('strokeBounds:', path.strokeBounds); // Прямоугольник с учётом толщины и скруглений

При strokeJoin = 'round' или strokeCap = 'round' strokeBounds расширяется больше, чем при стандартных значениях miter и butt.


Динамическое обновление strokeBounds

strokeBounds является вычисляемым свойством. Любое изменение:

  • strokeWidth
  • strokeCap
  • strokeJoin
  • геометрии фигуры (segments, curves, position)

автоматически обновляет прямоугольник strokeBounds. Не требуется ручное пересчитывание.

path.strokeWidth = 30;
console.log(path.strokeBounds); // Новый прямоугольник автоматически пересчитан

Важные нюансы

  • strokeBounds не всегда совпадает с визуально ожидаемым прямоугольником при трансформациях, таких как rotate, scale и shear. В этих случаях strokeBounds учитывает текущую трансформацию.
  • Для объектов без strokeColor или с strokeWidth = 0, strokeBounds равен bounds.

Применение в сложных композициях

strokeBounds используется для:

  • Проверки видимости объектов на холсте.
  • Расчёта коллизий и пересечений объектов.
  • Автоматического расположения объектов с учётом толщины линий.
  • Генерации интерактивных областей для клика или drag-and-drop.

Пример динамического ограничения движения объекта:

tool.onMouseD rag = function(event) {
    rect.position += event.delta;

    if (!view.bounds.contains(rect.strokeBounds)) {
        rect.position -= event.delta; // Ограничение движения с учетом толщины линии
    }
};

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


Использование strokeBounds обеспечивает точное позиционирование и взаимодействие элементов Paper.js, учитывая реальные размеры контура, а не только геометрические точки. Это критически важно для профессиональной работы с визуальными композициями и интерактивной графикой.