Отключение событий для объектов

В библиотеке Two.js каждый объект, будь то Shape, Group или Path, обладает собственным набором событий, которые позволяют отслеживать взаимодействие с пользователем, изменения состояния или обновления анимаций. События могут быть назначены через методы .bind() и .on(), а также через глобальные обработчики Two.js. Иногда возникает необходимость полностью или частично отключить события для определённого объекта, чтобы предотвратить их срабатывание.

Основные типы событий

Two.js поддерживает несколько категорий событий:

  1. DOM-события – мышь, клавиатура, сенсорные устройства. Пример: mouseover, mousedown, mouseup.
  2. События Two.js – изменения свойств объекта: change, update.
  3. Кастомные события – пользовательские события, созданные через .trigger().

Для отключения событий важно различать их категории: отключение DOM-событий и Two.js-событий производится разными способами.


Отключение DOM-событий

DOM-события добавляются к элементам SVG или Canvas через внутренние методы Two.js. Прямого метода off() для объектов Two.js нет, но есть несколько подходов:

1. Использование .unbind() для Two.js объектов

Каждый объект Two.js наследует метод .unbind(event, callback):

const circle = two.makeCircle(100, 100, 50);

function onCircleClick() {
  console.log('Клик по кругу');
}

circle.bind('click', onCircleClick);

// Отключение события
circle.unbind('click', onCircleClick);

Если передать только название события без функции:

circle.unbind('click');

будут удалены все обработчики данного события для объекта.

2. Манипуляции с DOM-элементом напрямую

Для объектов, привязанных к Canvas или SVG, можно отключать события через element.removeEventListener:

const ellipse = two.makeEllipse(200, 200, 80, 40);
two.update();

ellipse._renderer.elem.removeEventListener('mouseover', myMouseOverHandler);

Это особенно актуально, когда используются сторонние функции, которые напрямую добавляют слушатели на SVG-элементы.


Отключение событий изменения объекта

Two.js автоматически триггерит событие change при изменении свойств объекта. Для временного отключения таких событий можно использовать флаг:

let blockEvents = true;

const rect = two.makeRectangle(300, 300, 100, 50);

rect.bind('change', function() {
  if (blockEvents) return;
  console.log('Событие change сработало');
});

// Изменение свойства без вызова обработчика
blockEvents = true;
rect.width = 200;
rect.height = 100;
blockEvents = false;

Такой подход позволяет контролировать, когда события должны срабатывать, а когда – игнорироваться.


Отключение всех событий для объекта

Иногда требуется полностью отключить объект от всех событий Two.js. Для этого используют комбинацию методов .unbind() и обхода всех событий:

const polygon = two.makePolygon(400, 400, 5, 60);

// Предположим, есть несколько событий
polygon.bind('change', onChange);
polygon.bind('click', onClick);
polygon.bind('mouseover', onMouseOver);

// Полное отключение
polygon.unbind(); // убирает все события

Для DOM-событий необходимо отдельно обойти _renderer.elem и удалить все слушатели. Это можно сделать с помощью вспомогательной функции:

function removeAllDOMListeners(obj) {
  const elem = obj._renderer.elem;
  const clone = elem.cloneNode(true);
  elem.parentNode.replaceChild(clone, elem);
}

Этот метод удаляет все слушатели событий, назначенные через DOM, без изменения объекта Two.js.


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

  • Использовать .unbind(event, callback) для локального отключения событий. Это сохраняет остальные обработчики на объекте.
  • Использовать флаги для временного блокирования событий change и анимаций`. Такой подход безопасен и не требует удаления обработчиков.
  • Не трогать _renderer.elem, если можно обойтись стандартными методами Two.js. Прямое вмешательство в DOM может нарушить внутреннюю синхронизацию с библиотекой.
  • Для объектов в группах (Group) отключение событий распространяется на группу, но не на вложенные элементы. Для этого нужно отключать события на каждом дочернем объекте.

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

  1. События Two.js не наследуются автоматически, поэтому отключение события на родителе не убирает обработчики у дочерних элементов.
  2. При использовании анимаций через two.bind('update', ...) отключение событий объектов не предотвращает вызов глобальных обработчиков. Необходимо либо отключить обработчик глобально, либо проверять состояние объекта внутри колбека.
  3. Удаление всех DOM-событий не удаляет внутренние обработчики Two.js, поэтому для полного «отключения» объекта рекомендуется комбинировать оба подхода.