【问题标题】:Hover effect on SVG group elementsSVG 组元素上的悬停效果
【发布时间】:2013-10-15 18:41:00
【问题描述】:

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

【问题讨论】:

  • 你试过&lt;rect&gt;吗?

标签: html css svg


【解决方案1】:

使用模式

对于解决方案,您可以使用基于单个圆圈的pattern

在这种情况下,您不需要画很多圆来填充形状。

在填充 SVG 图案的图形时为圆形的克隆着色时会出现困难。

但可以通过为图案内的圆圈着色设置动画来解决此问题。

&lt;animate attributeName="fill" values="white;dodgerblue" begin="path1.mouseover" dur="0.1s" fill="freeze" /&gt;

<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>

【讨论】:

    【解决方案2】:

    另一个解决方案需要一点 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>

    【讨论】:

      【解决方案3】:

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

      g {
        pointer-events: bounding-box;
      }
      

      在 Chrome 中,它可以完美运行。也尝试了@vals 的答案,但这在 Firefox 中也不起作用。

      【讨论】:

        【解决方案4】:

        接受的答案对我不起作用。我找到了以下解决方案:

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

        【讨论】:

        【解决方案5】:

        你需要放一些东西来覆盖缺失的区域。

        更简单的方法是这个:

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

        updated fiddle

        【讨论】:

        • 太棒了。很简单。我一直在尝试精心设计的东西,例如带有一点 if js 的伴随路径,以将交互联系在一起。谢谢。
        • 聪明的人。希望我能给你多于一票。
        • 很好的提示,但这不适用于有笔划的线条!
        猜你喜欢
        • 2017-02-10
        • 1970-01-01
        • 2016-12-23
        • 2013-12-07
        • 2012-10-03
        • 2022-11-30
        • 2022-12-17
        • 1970-01-01
        • 2022-01-03
        相关资源
        最近更新 更多