Подтвердить что ты не робот

Делегирование событий в SVG-элементах

Я пытаюсь иметь общий обработчик кликов для всех элементов, которые я добавляю к холсту SVG. Но я не могу делегировать обработчик вновь созданным элементам.

Это код, который я пытался делегировать, но не повезло

$("#floor").on('click','.drawnLine', function() {
    //#floor is the SVG Element
    //.drawnLine is the <line> element that is added dynamically
    console.log($(this).data('index'));
});

Update: В руководстве jQuery .on() указано, что

Примечание. Делегированные события не работают для SVG.

Итак, теперь вопрос заключается в любом другом обходном пути для этой проблемы?

4b9b3361

Ответ 1

Когда jQuery не работает с SVG, вы можете использовать vanilla js. К счастью, каждый браузер, поддерживающий svg, также поддерживает прослушиватели событий. Чистое делегированное событие js не так уродливо:

$("#floor")[0].addEventListener('click', function(e) {
  // do nothing if the target does not have the class drawnLine
  if (!e.target.classList.contains("drawnLine")) return;
  console.log($(this).data('index'));
});

Но вы также можете создать свою собственную функцию для более четкого делегирования ваших событий.

Ответ 2

TL/DR: присоедините прослушиватель событий к родительскому элементу не SVG.

Примечание в документах jQuery несколько вводит в заблуждение.

Делегированные события не работают для SVG.

Вероятно, это должно быть...

Делегированные события не работают , когда слушатель подключен к SVG.

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

Прикрепление слушателя к элементу SVG будет не работать:

$("#floor").on('click','.drawnLine', function() {
    console.log($(this).data('index'));
});

Но привязка его к родительскому элементу будет работать:

$(document.body).on('click','#floor .drawnLine', function() {
    console.log($(this).data('index'));
});

Примечание: одна особенность, которую я заметил, заключается в том, что если целью события является элемент SVG, событие не будет полностью зависеть от document.body в iOS. Поэтому, если вы хотите, чтобы пользователи iOS могли запускать функцию вашего обработчика, вам нужно прикрепить свой прослушиватель событий к некоторому элементу между ними (например, к элементу div, в котором находится ваш SVG).