SVG组元素上的悬停效果

24
请原谅我的无知,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元素?


你试过使用<rect>标签吗? - robertc
5个回答

36

我尝试了推荐的解决方案,但并未生效。后来我找到了以下解决方法:

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

3
这正是我要找的内容。我唯一的问题是,“为什么这个值 bounding-box 没有在这个文档中描述:https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events?” - Rozar Fabien
1
我认为这是更好的解决方案,也是它真正的目的所在。 - Atherion

11

你需要放置东西来覆盖丢失的区域。

更简单的方法是这样的:

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

更新后的代码示例


太棒了。如此简单。我一直在尝试复杂的事情,比如使用一些js来连接交互,并附带路径。谢谢。 - Andy Place
太聪明了,真希望我可以给你不止一票。 - Ken Bellows
好的提示,但是这并不适用于具有描边的线条! - Ardian

4

@vals和@M_Willett的答案在MacOs(High Sierra)中的Firefox v60.0.2上不起作用。我正在使用:

g {
  pointer-events: bounding-box;
}

在Chrome中可以正常工作。也尝试了@vals的答案,但在Firefox中也无法正常工作。

3

使用图案

在解决方案中,您可以使用基于单个圆的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>


1
另一种解决方案需要一些 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>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接