Используя getIntersectionList()
, как показано в , этот очень похожий вопрос , вероятно, является самым чистым и наиболее эффективным решением.Однако он еще не поддерживается Firefox, поэтому я предложил решение, основанное на слегка адаптированной функции, взятой из этого ответа на другой вопрос .
Но осторожно: это, вероятно, оченьснижение производительности из-за комбинации события mousemove
с двумя циклами forEach
, повторяющимися по элементам DOM, в сочетании с повторным рендерингом, который может быть вызван скрытием / отображением элементов в течение минимального промежутка времени, в зависимости откак клиент будет обрабатывать и оптимизировать это.Так что это может привести к очень низкой производительности на слабых устройствах.Сказав это, похоже, он работает во всех основных браузерах (протестировано в Firefox, Chrome и Edge; хотя я не пробовал IE).
В комментариях к ответу во второй предоставленной мной ссылке естьпредложение для другой функции, использующей CSS pointer-events
вместо того, чтобы скрывать элементы.Нужно сравнить производительность этих двух подходов, чтобы решить, какой из них лучше использовать.
function getAllElementsFromPoint(rootEl, x, y) {
var elements = [];
var display = [];
var item = document.elementFromPoint(x, y);
while (item && item !== document.body && item !== window && item !== document && item !== document.documentElement && item !== rootEl) {
elements.push(item);
display.push(item.style.display);
item.style.display = "none";
item = document.elementFromPoint(x, y);
}
// restore display property
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = display[i];
}
return elements;
}
var svg = document.querySelector('svg.test');
svg.addEventListener('mousemove', function(ev) {
// first remove the class .hover from all elements
svg.querySelectorAll('*').forEach(function(subEl) {
subEl.classList.remove('hover');
});
// then get all elements at the mouse position
// and add the class "hover" to them
getAllElementsFromPoint(svg, ev.clientX, ev.clientY).forEach(function(hoveredEl) {
hoveredEl.classList.add('hover');
})
});
.left {
fill: yellow;
pointer-events: visible;
}
.left:hover,
.left.hover {
opacity: 0.3;
}
.middle {
fill: red;
pointer-events: visible;
}
.middle:hover,
.middle.hover {
opacity: 0.8;
pointer-events: visible;
}
.right {
fill: blue;
}
.right:hover,
.right.hover {
opacity: 0.6;
pointer-events: visible;
}
<svg class="test" width="500px" height="500px">
<g name="Layer" class="group">
<ellipse class="left" cx="120" cy="160" rx="80" ry="81" />
<ellipse class="right" cx="342" cy="271" rx="93" ry="97" />
<ellipse class="middle" cx="223" cy="176" rx="115" ry="153" />
</g>
</svg>