Порядок отрисовки

Paper.js использует объектно-ориентированную модель для работы с векторной графикой, где каждый элемент сцены представлен объектом типа Item или его потомками: Path, Raster, Group, Shape и другими. Понимание порядка отрисовки этих элементов критически важно для управления видимостью и перекрытием объектов на холсте.

Иерархия элементов

Каждый объект Paper.js существует в дереве сцены. Сцена (Project) содержит слои (Layer), а слои — дочерние элементы (Item). Порядок отрисовки определяется:

  1. Порядком элементов внутри слоя — элементы, созданные позднее, отрисовываются поверх предыдущих.
  2. Порядком слоев — верхний слой перекрывает нижний, независимо от порядка объектов внутри них.

Пример:

var path1 = new Path.Circle(new Point(100, 100), 50);
path1.fillColor = 'red';

var path2 = new Path.Circle(new Point(120, 120), 50);
path2.fillColor = 'blue';

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

Свойство z-order

Paper.js не имеет явного свойства zIndex, как в CSS, но порядок отрисовки можно контролировать методами:

  • bringToFront() — перемещает объект в конец списка дочерних элементов текущего слоя.
  • sendToBack() — перемещает объект в начало списка дочерних элементов текущего слоя.
  • insertAbove(item) и insertBelow(item) — вставляют объект относительно другого элемента.

Пример:

path1.bringToFront(); // path1 теперь поверх path2
path2.sendToBack();   // path2 теперь под path1

Эти методы изменяют порядок в массиве layer.children, что напрямую влияет на отрисовку.

Группы и порядок отрисовки

Группы (Group) позволяют объединять элементы и управлять ими как единым объектом. Порядок элементов внутри группы также важен:

  • Элементы группы отрисовываются в порядке добавления.
  • Группы как целое имеют свой порядок в слое.

Пример:

var group = new Group();
var rect = new Path.Rectangle([50, 50], [100, 100]);
rect.fillColor = 'green';
var circle = new Path.Circle([100, 100], 50);
circle.fillColor = 'yellow';

group.addChild(rect);
group.addChild(circle);

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

group.sendToBack();

Вся группа окажется под другими элементами слоя.

Слои и управление видимостью

Слои обеспечивают мощный механизм управления порядком отрисовки и видимостью элементов:

  • Элементы верхнего слоя всегда рисуются поверх нижних.
  • Свойства layer.visible = false и layer.opacity = 0.5 влияют на все дочерние элементы.
  • Метод activate() делает слой активным для добавления новых объектов, но не меняет его визуальный порядок.

Пример:

var layer1 = new Layer();
var layer2 = new Layer();

var rect1 = new Path.Rectangle([10, 10], [100, 100]);
rect1.fillColor = 'red';
layer1.addChild(rect1);

var rect2 = new Path.Rectangle([50, 50], [100, 100]);
rect2.fillColor = 'blue';
layer2.addChild(rect2);

Здесь синий прямоугольник из layer2 всегда будет поверх красного из layer1.

Динамическое изменение порядка

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

  • Перестановкой элементов через методы bringToFront() и sendToBack().
  • Изменением родителя через item.remove() и layer.addChild(item) для перемещения между слоями.
  • Использованием группы для управления множеством элементов одновременно.

Пример с анимацией:

function onFrame(event) {
    circle.position.x += 1;
    if(circle.position.x > view.size.width) {
        circle.position.x = 0;
        circle.bringToFront();
    }
}

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

Особенности перекрытия растров и векторных объектов

Paper.js одинаково обрабатывает Path, Shape и Raster, однако растры иногда требуют дополнительных настроек для корректного отображения:

  • Растры (Raster) отрисовываются как объекты Item и подчиняются тем же правилам порядка.
  • Для прозрачности используется свойство opacity.
  • Для слоев с большим количеством растров можно использовать blendMode для управления визуальным наложением.

Пример:

var raster = new Raster('image.png');
raster.position = view.center;
raster.opacity = 0.7;
raster.sendToBack();

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

  • Для предсказуемого порядка создавайте объекты в том порядке, в котором хотите их видеть.
  • Для сложных сцен используйте слои и группы для логической структуризации.
  • Динамическое управление порядком через методы bringToFront() и sendToBack() упрощает работу с интерактивными элементами.
  • Всегда учитывайте иерархию: порядок элементов внутри группы и слоев влияет на итоговую отрисовку.

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