Распространение событий: bubbling и capturing

В PixiJS система событий наследует принципы DOM, но адаптирована под графическую сцену. Каждый интерактивный объект (DisplayObject) может получать события ввода, такие как click, pointerdown, pointerup, mousemove и другие. Основная особенность — двухфазное распространение событий: capturing (погружение) и bubbling (всплытие).


Capturing (погружение)

Фаза capturing происходит на пути от корня сцены к целевому объекту. Она позволяет родительским контейнерам перехватывать события до того, как они достигнут дочернего объекта.

  • Механизм: событие проходит сверху вниз по иерархии.
  • Использование: полезно для реализации глобальных фильтров событий, например, блокировки кликов на определённой зоне сцены.
  • Регистрация слушателя: при использовании on() можно указать параметр capture, хотя в PixiJS это реализуется через interactiveChildren и порядок добавления слушателей.
const parent = new PIXI.Container();
const child = new PIXI.Sprite.from('image.png');

parent.addChild(child);
parent.interactive = true;
child.interactive = true;

parent.on('pointerdown', (event) => {
    console.log('Capturing: родитель');
}, true); // третий параметр — capture

Здесь событие сначала будет обработано родителем при фазе погружения, а затем перейдёт к дочернему элементу.


Bubbling (всплытие)

Фаза bubbling срабатывает после того, как событие достигло целевого объекта. Оно распространяется снизу вверх, от целевого элемента к корню.

  • Механизм: событие сначала обрабатывается самим объектом, затем его родителями, пока не дойдёт до корня сцены.
  • Контроль всплытия: метод stopPropagation() останавливает дальнейшее распространение события.
  • Применение: позволяет родителям реагировать на действия дочерних элементов без необходимости добавлять слушателей на каждый объект.
child.on('pointerdown', (event) => {
    console.log('Целевой объект');
    event.stopPropagation(); // событие больше не всплывает
});

parent.on('pointerdown', (event) => {
    console.log('Родитель всплытия');
});

Если stopPropagation() не вызывается, родитель также обработает событие после дочернего объекта.


Иерархия и интерактивность

Для корректного распространения событий важно правильно настраивать иерархию объектов и их интерактивность:

  • interactive = true — объект реагирует на события.
  • interactiveChildren = true — контейнер может передавать события своим детям.
  • Порядок добавления слушателей влияет на обработку, особенно если несколько слушателей зарегистрированы на одном объекте.

Пример с контейнером и вложенными объектами:

const stage = new PIXI.Container();
const container = new PIXI.Container();
const sprite = new PIXI.Sprite.from('image.png');

container.addChild(sprite);
stage.addChild(container);

stage.interactive = true;
container.interactive = true;
sprite.interactive = true;

stage.on('pointerdown', () => console.log('stage'));
container.on('pointerdown', () => console.log('container'));
sprite.on('pointerdown', () => console.log('sprite'));

Нажатие на sprite приведёт к следующей последовательности (без stopPropagation()): Capturing: stage → container → sprite Bubbling: sprite → container → stage


Использование event.data

События в PixiJS передают объект event, содержащий данные о взаимодействии:

  • event.data.global — координаты указателя относительно сцены.
  • event.data.getLocalPosition(target) — координаты относительно конкретного объекта.
  • event.stopPropagation() — остановка всплытия.
  • event.currentTarget — объект, на котором вызвался обработчик.
  • event.target — изначальный объект, на котором произошло событие.

Это позволяет реализовывать точные взаимодействия с элементами сцены, фильтровать события по координатам и контролировать распространение.


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

  1. Для сложных сцен с вложенными контейнерами лучше явно включать interactiveChildren, чтобы события корректно достигали всех объектов.
  2. Для глобальных обработчиков использовать фазу capturing, чтобы фильтровать события до попадания на дочерние объекты.
  3. Остановка всплытия рекомендуется использовать, когда дочерний объект полностью обрабатывает событие и не требует участия родителей.
  4. Порядок добавления слушателей важен при одновременном использовании capturing и bubbling: сначала добавляются обработчики для capturing, затем для bubbling.

Система capturing и bubbling в PixiJS обеспечивает мощный контроль над событиями в интерактивной сцене, позволяя реализовывать сложные взаимодействия, не перегружая код множеством отдельных слушателей. Контейнеры и спрайты могут как перехватывать события, так и реагировать на них на разных уровнях иерархии.