Управление состоянием

Paper.js построен на концепции декларативного рисования, где все объекты сцены (Paths, Raster, Layer, Group) находятся в иерархической структуре и управляются через состояния проекта и сцены. Понимание этих состояний является ключевым для построения динамических, интерактивных приложений на Canvas.


Объект project и текущее состояние

В Paper.js каждый холст (canvas) связывается с объектом Project, который хранит все слои и элементы:

var project = new Project(document.getElementById('myCanvas'));
  • project.activeLayer — текущий активный слой для рисования.
  • project.selectedItems — массив выделенных элементов.
  • project.currentStyle — объект, содержащий свойства заливки, обводки и прозрачности, которые будут применяться к новым элементам.

Изменение activeLayer напрямую меняет, куда будут помещены новые объекты:

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

project.activeLayer = layer1;
new Path.Circle(new Point(50, 50), 30); // Нарисован в layer1

project.activeLayer = layer2;
new Path.Circle(new Point(150, 50), 30); // Нарисован в layer2

Таким образом, состояние активного слоя определяет контекст рисования.


Управление стилями через currentStyle

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

project.currentStyle = {
    strokeColor: 'red',
    strokeWidth: 5,
    fillColor: 'yellow'
};

var rect = new Path.Rectangle(new Point(10, 10), new Size(100, 50));
  • Если стиль объекта не указан явно, используются значения из currentStyle.
  • Можно сохранять предыдущие состояния стилей через копирование объекта Style:
var previousStyle = project.currentStyle.clone();
project.currentStyle.strokeColor = 'blue';

Это позволяет создавать временные состояния для рисования разных объектов с разными стилями без глобального изменения всех элементов.


Слои и их состояние

Слои (Layer) — это основной инструмент управления группами объектов и состоянием сцены. Они поддерживают следующие возможности:

  • Порядок рендеринга: объекты на верхних слоях перекрывают нижние.
  • Видимость: свойство layer.visible управляет видимостью всей группы объектов.
  • Активность: свойство layer.activate() переводит слой в текущее состояние рисования.
  • Выделение: layer.selected позволяет временно выделять все объекты слоя для редактирования.

Пример управления слоями:

var backgroundLayer = new Layer();
backgroundLayer.activate();
var bg = new Path.Rectangle(new Point(0,0), view.size);
bg.fillColor = 'lightgray';

var mainLayer = new Layer();
mainLayer.activate();
var circle = new Path.Circle(new Point(150,150), 50);
circle.fillColor = 'blue';
  • Здесь порядок активации слоев задает контекст рисования, а порядок слоев определяет визуальное наложение.

Состояние выделения объектов

Paper.js хранит состояние выделения объектов отдельно от их внешнего вида:

  • item.selected — позволяет отметить объект как выделенный.
  • project.selectedItems — массив всех выделенных объектов на текущем проекте.
  • Выделение не влияет на стиль напрямую, но можно настроить item.selectedColor для визуальной подсветки.

Пример:

var path = new Path.Circle(new Point(100, 100), 40);
path.selected = true;
path.selectedColor = 'red';

С помощью событий можно динамически менять состояние выделения:

path.onCl ick = function() {
    this.selected = !this.selected;
};

Управление состоянием через события

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

  • onFrame(event) — вызывается на каждый кадр, удобно для анимаций и изменения состояний.
  • onMouseDown, onMouseDrag, onMouseUp — позволяют изменять объекты или активные слои по взаимодействию пользователя.

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

var circle = new Path.Circle(new Point(150,150), 30);
circle.fillColor = 'green';

circle.onMouseD rag = function(event) {
    this.position += event.delta; // Изменяем состояние позиции объекта
};

Состояние объекта (position) изменяется каждый кадр при перетаскивании, сохраняя при этом остальные свойства неизменными.


Сохраняемое состояние и undo/redo

Paper.js поддерживает копирование объектов и слоев, что позволяет реализовать собственные механизмы undo/redo:

var copy = circle.clone(); // Сохраняем текущее состояние объекта
copy.position.x += 50; // Модифицируем копию без влияния на оригинал

Для глобального управления состояниями можно использовать:

  • layer.children — доступ ко всем объектам слоя.
  • project.layers — доступ ко всем слоям проекта.
  • item.remove() и item.addChild() — динамическое изменение структуры сцены.

Иерархическое состояние с группами

Группы (Group) позволяют объединять несколько объектов и управлять их состоянием как единым целым:

var group = new Group();
var rect = new Path.Rectangle(new Point(10,10), new Size(50,50));
var circle = new Path.Circle(new Point(50,50), 25);

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

group.position.x += 100; // Сдвигаем все объекты вместе
  • Состояние группы влияет на все дочерние элементы.
  • Изменение видимости, масштаба или вращения группы автоматически применяется ко всем детям.

Работа с глобальным состоянием сцены

Объект view отражает глобальное состояние окна Canvas:

  • view.size — размеры холста.
  • view.center — центр текущей сцены.
  • view.onResize — событие, изменяющее состояние сцены при изменении размеров окна.
  • view.zoom и view.matrix — позволяют управлять глобальной трансформацией всего проекта.

Пример адаптивного масштабирования:

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

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


Итоговые принципы управления состоянием

  1. Проект определяет глобальный контекст: активный слой, стиль и выделенные элементы.
  2. Слои формируют иерархию объектов и порядок рендеринга.
  3. Выделение объектов и групп позволяет управлять интерактивностью без изменения стиля.
  4. События обеспечивают динамическое обновление состояний объектов и сцены.
  5. Копирование и клонирование объектов служит сохранению и восстановлению состояния.

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