document.addEventListener не работает с загруженным svg
Я пытаюсь создать проект, в котором пользователь может щелкнуть изображение, а затем загружается интерактивный .svg (внутри тега object). Для этого мне нужно отслеживать движение мыши по всему экрану (а не только .svg) после того, как произошла загрузка.
Однако ни document.addEventListener, ни window.addEventListener не работают с *.svg. Они просто работают за его пределами. Есть ли способ исправить это без необходимости комбинировать document.addEventListener и конкретный interactiveSVG.addEventListener`?
Вот мой код (отредактированный):
let firstImage = document.querySelector('#my-first-img');
let objectSVG = document.querySelector('#svg-obj');
let interactiveSVG;
firstImage.addEventListener('click', e => {
objectSVG.data = `mySVG.svg`;
objectSVG.addEventListener('load', e => {
interactiveSVG = objectSVG.getSVGDocument();
document.addEventListener('mousemove', e => {
console.log(e.clientX);
});
});
});
Свободный перевод вопроса document.addEventListener not working on loaded svg от участника @Fede.
Ответы (1 шт):
Насколько я знаю, SVG внутри <object> несколько вас ограничивает. Существуют обширные функции для событий pointer-events CSS, которые могут применяться к элементам SVG, которые, к сожалению, не может предоставить <object>. Но если вы назначите pointer-events: none для SVG, это будет проигнорировано, поэтому события указателя будут срабатывать непосредственно над SVG, но event.target будет ближайшим предком DOM-элемента SVG.
Для SVG в <object> вам нужен фактический тег <style> внутри <object> и добавить pointer-events: none
<object class="map" data="path/to/image.svg" type="image/svg+xml">
<style>
.map {
pointer-events: none;
}
</style>
</object>
В приведенном ниже примере показано нормальное поведение указателя при наведении или нажатии на SVG. Имейте в виду, что с pointer-events: none, на самом деле все взаимодействия происходят в DOM.
Применение
Наведите указатель мыши на всю страницу и обратите внимание на координаты X,Y, отображаемые в левом углу. SVG обведен красной пунктирной линией, обратите внимание, что события mousemove срабатывают, когда курсор находится над SVG.
Щелкните снаружи и внутри SVG. При каждом щелчке будет установлен значок флага (наведите указатель мыши на флаг, и появится всплывающая подсказка с его координатами X,Y). Это возможно, потому что каждый флаг имеет позицию: абсолютная, а тело — позиция: относительная.
Примечание:
координаты флагов и кодов, отображаемых в углу, не точны, поскольку флаги находятся на смещении измерений .getBoundingClientRect() и clientX/Y
Для установки маркеров на карте, кликнете по месту
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
html {
font: 1.5ch/1 Consolas;
}
html,
body {
width: 100%;
height: 100%;
}
body {
position: relative;
}
fieldset {
width: max-content;
padding: 0;
}
mark {
position: absolute;
background: transparent;
}
mark:after {
content: '\1f6a9';
font-size: 1.25rem;
}
</style>
</head>
<body>
<fieldset>
<legend><output class="view"></output></legend>
<object class="map" data="https://upload.wikimedia.org/wikipedia/commons/4/41/Simple_world_map.svg" type="image/svg+xml">
<style>
.map {
transform: scale(0.75);
outline: 1px dashed red;
pointer-events: none;
}
</style>
</object>
</fieldset>
<script>
document.onmousemove = trackPoint;
document.onclick = markPoint;
function trackPoint(e) {
const view = document.querySelector('.view');
view.value = `X: ${e.clientX.toString().padStart(3, '0')} : Y: ${e.clientY.toString().padStart(3, '0')}`;
}
function markPoint(e) {
const mark = document.createElement('mark');
document.body.appendChild(mark);
getCoords.call(mark, e);
}
function getCoords(e) {
const clk = e.target;
const rect = clk.getBoundingClientRect();
const oX = Math.floor(e.clientX - rect.left);
const oY = Math.floor(e.clientY - rect.top);
this.style.left = oX + 'px';
this.style.top = oY + 'px';
this.title = `[${oX}, ${oY}]`;
}
</script>
</body>
</html>
