Влияние Hover на элементы группы SVG

Пожалуйста, извините мое невежество, SVG очень новичок. Я пытаюсь получить эффект зависания для группы элементов в моем встроенном SVG. Каждая группа элементов представляет собой тесно расположенную совокупность кругов. Я могу добиться этого эффекта зависания с помощью css, но, очевидно, это будет работать только тогда, когда мышь расположена над кругом. Я хочу, чтобы эффект работал, когда мышь находится над всей областью, в которой есть круги, поэтому пробелы и круги объединены.

<style>
svg {
  height: 220px;
  width: 400px;
  background: grey;
}

.na circle,
.as circle {
  fill: white;
}

.na:hover circle {
  fill: blue;
}
</style>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <g class="na">
    <circle cx="35%" cy="2.85%" r="2.8" />
    <circle cx="36.75%" cy="2.85%" r="2.8" />
    .
    .
    <circle cx="38.5%" cy="8.55%" r="2.8" />
    <circle cx="40.25%" cy="8.55%" r="2.8" />
  </g>    
</svg>

http://jsfiddle.net/c3EaX/

Смотрите, перемещая мышь над группой, наведение мерцает, когда вы проходите между кругом и пространством между ними.

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

Ответ 1

Вам нужно поместить что-то, чтобы покрыть недостающую область.

Более простым способом будет этот:

.na circle,
.as circle {
    fill: white;
    stroke: transparent;
    stroke-width: 4px;
}

обновленная скрипка

Ответ 2

Принятый ответ не помог мне. Я нашел следующее решение:

g {
  pointer-events: bounding-box;
  opacity: 0.4;
}
g:hover {
    opacity: 1;
}

Ответ 3

Ответы @vals и @M_Willett не будут работать в Firefox v60.0.2 в MacO (High Sierra). Я использую:

g {
  pointer-events: bounding-box;
}

В Chrome так и работает отлично. Пробовал ответ и по @vals, и это не работает в Firefox.

Ответ 4

Другое решение требует немного JavaScript, чтобы программно получить ограничивающий прямоугольник группы. Единственным недостатком является то, что эффект наведения будет применяться к этому прямоугольнику вместо фактической формы группы.

const group = document.getElementById('group');
const box = group.getBoundingClientRect();

document.addEventListener('mousemove', e => {
  const hover = e.clientX > box.left && e.clientX < box.right && e.clientY > box.top && e.clientY < box.bottom;
  if (hover) {
    group.classList.add('hovered');
  } else {
    group.classList.remove('hovered');
  }
});
body {
  background: gray;
}

g > circle {
  fill: white;
}

g.hovered > circle {
  fill: blue;
}
<svg>
  <g id="group">
    <circle cx="30%" cy="20%" r="5"></circle>
    <circle cx="60%" cy="20%" r="5"></circle>
    <circle cx="45%" cy="50%" r="5"></circle>
  </g>
</svg>

Ответ 5

Использовать шаблон

Для решения вы можете использовать pattern который основан на одном круге.

В этом случае вам не нужно рисовать много кругов, чтобы заполнить форму.

Сложности возникают при раскрашивании клонов круга при заполнении фигуры рисунком SVG.

Но эту проблему можно решить, анимировав окраску окружностей внутри рисунка.

<animate attributeName="fill" values="white;dodgerblue" begin="path1.mouseover" dur="0.1s" fill="freeze"/>

<style>
#ptn1 {
fill:dodgerblue;
}
</style>
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
	     width="200" height="200" viewBox="0 0 100 100" >  
<defs>
<pattern id="ptn1"   
  x="0" y="0" width="5" height="5"
  patternUnits="userSpaceOnUse">
<circle cx="3" cy="3" r="2" fill="none" stroke="grey" stroke-width="0.5" >
  <animate attributeName="fill" values="white;dodgerblue" begin="path1.mouseover" dur="0.3s" fill="freeze" />
   <animate attributeName="fill" values="dodgerblue;white" begin="path1.mouseout" dur="0.3s" fill="freeze" />
 </circle>
</pattern>
</defs>		 

<path id="path1" d="m10 50 v-5h5 v-5h5 v-5h5 v-5h5 v-5h5 v5h5 v5h5 v5h5 v5h5 v5h-45 "  stroke="none" fill="url(#ptn1)" />
</svg>