如何使SVG图像中的透明部分可点击?

23
我有一个SVG,使用:hover改变颜色。只有当我悬停在SVG的实心部分上时才有效,而不是透明部分。我想知道如何让SVG与鼠标悬停在整个SVG上的任何位置进行交互。这样做的目的是使SVG成为链接,并且链接仅在SVG的某些部分可点击。我不仅想要针对特定情况的解决方案,还要为许多情况提供解决方案(如果我希望将SVG的不同部分设置为可点击)。我的SVG元素直接连接到CSS并使用

1
将:hover放在svg元素上?(除非我漏掉了什么) - Michael Mullany
设置高度和宽度。 - itsclarke
1
将其包装在一个 div 中,并将 hover 放在该 div 上? - nickspiel
这样做是可行的,但它会使整个东西成为一个链接,而不是指定到任何特定区域。 - Sam Sabin
1
jsfiddle不存在。 - Ram Tobolski
显示剩余3条评论
7个回答

23

SVG2新增了一个关键词bounding-box到'pointer-events',以使其更易于使用。它适用于组和形状,在您的示例中,它将变为:

.test {
  pointer-events: bounding-box;
  stroke: #5ff6ff;
}
.test:hover {
  stroke: #555555;
}

请查看jsfiddle。现在这应该可以在Chrome Canary或Opera Dev版本中工作。

这取决于形状,但也有可能在当前流行的浏览器中实现。例如,在最大的形状上使用pointer-events="all",然后巧妙地使用CSS选择器来将描边应用到所需的位置。这有点棘手,因为您可能希望描边应用于组,尽管实际上悬停的元素是组内的形状。

另一种选择是在


8
现有的“指针事件”问题答案帮助我找到了这个解决方法:
<svg id="example" pointer-events="bounding-box" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 300">
pointer-events="bounding-box" 最好放在 SVG 标签内,如果您有透明区域需要点击,例如带有图标或链接到嵌入式链接(定义为 xlink:href)的网站主页的标志(如上所示)。请注意保留 HTML 标记。

这个得到了多少支持?似乎不太好 :( - Shikyo

3

您可以在测试<g>中包含 pointer-events="visible",并在其中调用一个函数,该函数位于父HTML中(在IE/CH/FF中经过测试)例如:

<svg xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg3036" version="1.1" inkscape:version="0.48.2 r9819" width="58" height="58">
         <g pointer-events="visible" onclick="parent.testHover()" class="test" fill="none" stroke="black" stroke-width="2">
  <path d="M 8.1 32.8 C 7.1 30.1 0.3 -4.6 11.1 4.9 21.9 14.5 15.9 12.8 29 12.8 42.1 12.9 36.1 14.6 46.9 5.1 57.7 -4.5 50.9 30.3 49.9 32.9 48.9 35.6 37.6 54.8 29 54.7 20.4 54.6 9.1 35.4 8.1 32.8 z" id="path3119" inkscape:connector-curvature="0" sodipodi:nodetypes="zzzzzzz" class="wolf"/>
  <path d="M 31.5 23.3 46.6 21" id="path5212" inkscape:connector-curvature="0" sodipodi:nodetypes="cc" class="eyes"/>
  <path d="M 33 23 C 32.3 33.9 45 22 45.2 21" id="path5260" inkscape:connector-curvature="0" sodipodi:nodetypes="cc" class="eyes"/>
  <path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path5262" d="M 26.5 23.3 11.4 21" class="eyes"/>
  <path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path5264" d="M 25 23 C 25.7 33.9 13 22 12.8 21" class="eyes"/>
  </g>
</svg>

编辑 - 已添加。

我已经测试了使用您的SVG作为 <img> 的src,而不是 <object> 并将其放入链接中。 它在所有浏览器中都可点击。 没有必要添加 pointer-events 或函数调用。 因此,您可以使用 img 而不是 object。


这确实使内部可点击,但是否适用于我想要点击的任何区域?这也可以通过向“wolf”元素添加透明填充来实现。但我需要它成为一个链接,怎么做呢?将其包装在<a>标签中不起作用。 - Sam Sabin

1

我在2014年发布了这个问题。基本上,我试图解决两个问题,如何使svg保留对透明部分的悬停效果(特别是在使用object标签的svg中,以便可以轻松使用悬停效果),以及如何使svg的各个方面可以用作独立链接。

我尝试了很多复杂的解决方案,最终找到了第一个问题的非常简单的解决方案。只需设置fill(任何颜色都可以,只要不设置为fill: none),并设置fill-opacity: 0。这将保留指针单击事件,同时保持svg透明。事后看来很合理,但如果您正在使用预制的svg,其中fill可能已设置为none(适当地设置)可能会令人困惑。

以下是实际应用的示例:

<circle cx="100" cy="75" r="50" style="fill: green; fill-opacity: 0;" />

这将创建一个圆形,保留任何指针事件(如悬停),尽管完全透明。
我应该在当时发布一个答案,提供这个解决方案,因为我认为这是大多数找到这个问题的人可能正在寻找解决方案的问题。但当时我觉得答案还没有完成。我忘了这个问题,以及第一个问题的解决方案。但我决定重新访问这个问题,并给予一些非常需要的解决方案。
自从我提出这个问题以来,在svg中的标签已经得到了更新,现在很容易将链接应用于svg的各个部分。它的工作方式与您想象的完全相同:<a href="" target="_blank">...在此处放置您的SVG元素</a> ,这在以前并不完全是这种情况(或者至少我以前不知道它是如何工作的)。第二个问题已解决!
这里有一个代码沙盒,展示了嵌入了标签的svg上下文中解释了解决方案的工作原理:
演示

0

有一个可以通过使用滤镜来实现的技巧。滤镜效果可以将填充颜色变为透明,而不会影响到其可点击性。在下面的例子中,您可以给图形添加一个半透明填充颜色,然后使用滤镜将其去除。

.wolf{
    fill:   blue;
     fill-opacity:  0.09;
    stroke-width:   3.672px;
    stroke-linejoin:    round;
} /*.wolf:hover {
    stroke: #777777;
}*/

.eyes{
    fill:   none;
    fill-opacity: 0;
    stroke-width:   1.26708329px;
}

    <defs>
        <filter id="greenscreen">
        <feComponentTransfer>
            <feFuncA type="table" tableValues="0 0 .2 .3 .4 .5 .6 .7 .8 .9 1"/>
        </feComponentTransfer>
    </filter>
    </defs>
  <g class="test" filter="url(#greenscreen)">

etc.

如果你的填充颜色是透明的,这会有什么影响呢? - Sam Sabin

0

编辑: svg:hover .test { stroke: #555555}

忽略之前的答案(下面),它是针对不同的问题。

创建一个空的透明对象 - 即大小和形状与 <svg> 相同的 <rect>,并将其放置在 </a></svg> 之前(不要包裹!)。


0
如果你想最终得到一个有效的HTML文档,那么请将SVG元素用锚点标签包围起来,以便将其转换为链接。
此外,不要忘记将链接转换为块级或内联块级元素(这取决于你的需求)。

我的SVG已经链接在一个对象标签内。我不想改变这个,否则我将不得不使用内联CSS来处理SVG。现在,SVG通过外部样式表与CSS相连。 - Sam Sabin
那么我建议你将你的SVG转换成字体。这似乎比你想要制作的更有效。请参考http://fortawesome.github.io/Font-Awesome/,并查看http://fontastic.me/以创建自己的字体。创建自己的SVG库,并以模块化的方式在网站中反复使用它。 - Oz Lodriguez
这是一个相当不错的解决方案,但我想知道如何完成这个任务。 - Sam Sabin

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