Обработка ресизов

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

Свойство view и его роль

В Paper.js объект view представляет собой интерфейс между сценой и холстом. Он содержит размеры холста, координаты центра, трансформации и позволяет управлять масштабом отображения.

Ключевые свойства view:

  • view.size – объект { width, height }, отражающий текущий размер холста.
  • view.bounds – прямоугольник, описывающий границы видимой области.
  • view.center – центр видимой области, автоматически пересчитывается при изменении размеров.

Автоматическое обновление размера холста

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

view.onRes ize = function(event) {
    console.log('Новый размер холста:', view.size.width, view.size.height);
};

Параметр event содержит информацию о предыдущем размере (event.oldSize) и текущем размере (event.size), что позволяет рассчитывать масштабирование или смещение объектов.

Масштабирование содержимого

Для сохранения пропорций объектов при изменении размеров холста можно использовать метод view.scale():

view.onRes ize = function(event) {
    const scaleX = event.size.width / event.oldSize.width;
    const scaleY = event.size.height / event.oldSize.height;
    activeLayer.scale(scaleX, scaleY);
};
  • activeLayer – слой, содержащий все объекты, которые нужно масштабировать.
  • scaleX, scaleY – коэффициенты масштабирования по горизонтали и вертикали.
  • Метод scale сохраняет относительные позиции объектов, позволяя адаптировать рисунок под новые размеры холста.

Привязка объектов к краям

Для интерфейсных элементов часто нужно закреплять объекты к краям холста. Paper.js предоставляет координаты через view.bounds:

const circle = new Path.Circle({
    center: view.bounds.topLeft.add([50, 50]),
    radius: 30,
    fillColor: 'red'
});

view.onRes ize = function(event) {
    circle.position = view.bounds.topLeft.add([50, 50]);
};

Использование view.bounds.topLeft, view.bounds.topRight, view.bounds.bottomLeft, view.bounds.bottomRight позволяет легко привязывать объекты к нужным углам и сохранять относительное расположение при изменении размеров холста.

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

Для объектов, которые должны оставаться по центру холста:

const rectangle = new Path.Rectangle({
    point: [0, 0],
    size: [100, 60],
    fillColor: 'blue'
});
rectangle.position = view.center;

view.onRes ize = function(event) {
    rectangle.position = view.center;
};

view.center автоматически обновляется при ресайзе, что позволяет избежать ручного пересчета координат.

Адаптация координатной системы

Иногда требуется не просто перемещать объекты, а изменять систему координат. Для этого Paper.js поддерживает метод view.matrix, который позволяет трансформировать всю сцену:

view.onRes ize = function(event) {
    const scaleFactor = event.size.width / event.oldSize.width;
    view.matrix.setToScale(scaleFactor, scaleFactor);
};

Использование view.matrix удобно для масштабирования всей сцены с сохранением относительных координат и размеров объектов.

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

При интенсивном ресайзе важно учитывать производительность:

  • Не выполнять сложные пересчеты на каждый пиксель изменения размера. Можно использовать requestAnimationFrame для дебаунса.
  • Масштабировать слои вместо отдельных объектов для уменьшения количества операций.
  • Для статичных объектов хранить исходные размеры и позиции, чтобы при ресайзе можно было пересчитывать их относительно нового размера холста.

Пример комплексного ресайза

const circle = new Path.Circle({
    center: view.center,
    radius: 40,
    fillColor: 'green'
});

const square = new Path.Rectangle({
    point: [50, 50],
    size: [80, 80],
    fillColor: 'orange'
});

const initialSize = view.size.clone();

view.onRes ize = function(event) {
    const scaleX = event.size.width / initialSize.width;
    const scaleY = event.size.height / initialSize.height;

    circle.position = view.center;
    square.position = view.bounds.bottomRight.subtract([90 * scaleX, 90 * scaleY]);

    circle.scale(Math.min(scaleX, scaleY));
    square.scale(Math.min(scaleX, scaleY));
};

В этом примере:

  • circle остается по центру.
  • square привязан к правому нижнему углу.
  • Масштабирование применяется пропорционально, с учетом исходного размера холста.

Обработка ресайза в Paper.js строится вокруг объекта view и событий onResize. Использование координат view.bounds, центра view.center и методов scale и matrix позволяет гибко адаптировать графику к изменениям размеров холста, сохраняя пропорции и позиционирование объектов.