SVG USE元素和:悬停样式

时间:2012-12-02 20:20:58

标签: css svg hover styling

我正在尝试使用CSS :hover伪类来设置<defs> <use>标记中嵌入的SVG元素,但它似乎不起作用: - /这是我的代码:

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
 <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8"/>
 <style type="text/css" media="screen">
        .active { fill: #0BE; }
        .active:hover { opacity: 0.8; stroke: #F0F; stroke-width: 4px; }
        .active2 #p2 { fill: #0BE; }
        .active2:hover #p2 { opacity: 0.8; stroke: #F0F; stroke-width: 4px; }
        #p2:hover { opacity: 0.8; stroke: #F0F; stroke-width: 4px; }
    </style>
</head>
<body>


<svg version="1.1" width="640" height="480"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink">

 <defs>
  <polygon id="p0" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active"/>
  <g id="gr1">
      <polygon id="p1" points="130,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6"/>
      <polygon id="p2" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active"/>
  </g>
 </defs>

 <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)"/>
    <use xlink:href="#p0" transform="translate(250,0)"/>
    <use xlink:href="#p0" transform="translate(460,0)" class="active" />
 </g>
 <g transform="translate(100,300)">
    <polygon id="style" points="110,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="foo"/>
    <use xlink:href="#gr1" transform="translate( 350,2)" class="active2"/>
 </g>

</svg>

</body>
</html>

我希望它的工作方式是当用户将鼠标指针放在嵌入元素上时,其内部元素的类“active”将改变其样式。当我直接从<defs>嵌入一个形状并将CSS类应用于嵌入它的<use>时,它就可以工作。但它不适用于通过<use>嵌入的组内的任何类或ID。

如何解决?

或许还有更好的方法吗?

当用户将鼠标悬停在嵌入对象中时,我只需更改此特定部分,而不是整个组。这是因为该组的不同部分将应用不同的样式,并且当鼠标悬停时它们需要以不同的方式进行更改。

编辑:我想要的内容

我想要的是将<defs>中的一个“库对象”嵌入到我的SVG文档中的许多不同位置的方法。这个对象的某些部分需要使用CSS中的自定义颜色进行样式设置,因为我需要轻松自定义这些颜色,而无需更改库对象的代码。

然后,当鼠标指针位于这样的“活动”对象上方时,我需要通过不同的方式设置其部件的方式来向用户发出信号:当鼠标指针悬停在它们上方时,这里和那里显示一些明亮的轮廓以显示可点击区域的形状。

不幸的是,我无法将样式应用于<use>元素的子元素,因为它们不是DOM中<use>的子元素(正如其他人已经提到的那样)。我可以将一些样式应用于<defs>部分内的元素,因为它们位于DOM中,并且可以通过CSS选择器进行寻址,但它们不能悬停,因为它们是不可见,因此将:hover伪类应用于它们是行不通的。如果将此类应用于<use>,它也不起作用,因为我无法再选择正确的子元素(它们不是<use>的子元素)。所以我没有任何钩子来应用那些:hover伪类。

也许我的问题有其他解决办法吗?

3 个答案:

答案 0 :(得分:27)

您无法处理通过使用引用的元素。 The specs说:

  

对于支持使用CSS进行样式处理的用户代理,将引用元素概念性深度克隆到非公开DOM树中也会复制由引用元素引用的CSS级联([CSS2],第6章)产生的任何属性值,它的内容。 CSS2选择器可以应用于原始(即引用)元素,因为它们是正式文档结构的一部分。 CSS2选择器不能应用于(概念上)克隆的DOM树,因为它的内容不是正式文档结构的一部分。

尽管如此,Firefox支持通过使用虫洞来处理“虚拟”元素。所有其他浏览器都没有。

如果您为引用元素指定填充/描边值currentColor,然后更改color元素的<use>属性,那么浏览器支持更多填充或描边颜色在悬停。像这样:

<svg version="1.1" width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

  <style type="text/css">
    #p0 {fill:currentColor}
    #use1:hover {color:green}
    #use2:hover {color:red}
    #use3:hover {color:blue}
  </style>

  <defs>
    <polygon id="p0" points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" class="active" />
  </defs>

  <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)" id="use1" />
    <use xlink:href="#p0" transform="translate(250,0)" id="use2" />
    <use xlink:href="#p0" transform="translate(460,0)" id="use3" />
  </g>
</svg>

所有主流浏览器(FF,Chrome,IE,Safari)均支持此功能。只有Opera似乎不喜欢它。当然,缺点是这种方法只能改变一种颜色。

因此,如果只是改变颜色,可以采用不同的方法来使用滤镜。例如,使用<feColorMatrix>,您可以使用颜色矩阵将一种颜色转换为另一种颜色,如下所示:

<svg version="1.1" width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

  <style type="text/css">
    #p0 {fill: currentColor}
    #use1:hover {filter: url(#filter1)}
    #use2:hover {filter: url(#filter2)}
    #use3:hover {filter: url(#filter3)}
  </style>

  <defs>
    <g id="p0">
      <polygon points="100,0 50,86.6 -50,86.6 -100,0 -50,-86.6 50,-86.6" fill="red" />
      <rect width="50" height="70" fill="green" />
      <circle cx="-20" cy="-30" r="30" fill="blue" />
    </g>
  </defs>

  <filter id="filter1">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 1 0 0 0 
                     1 0 0 0 0 
                     0 0 1 0 0 
                     0 0 0 1 0" />
  </filter>
  <filter id="filter2">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 0 1 0 0 
                     1 0 0 0 0 
                     0 1 0 0 0 
                     0 0 0 1 0" />
  </filter>
  <filter id="filter3">
    <feColorMatrix type="matrix" in="SourceGraphic" values="0 1 0 0 0 
                     0 0 1 0 0 
                     1 0 0 0 0 
                     0 0 0 1 0" />
  </filter>

  <g transform="translate(70,100)">
    <use xlink:href="#p0" transform="translate(40,0)" id="use1" />
    <use xlink:href="#p0" transform="translate(250,0)" id="use2" />
    <use xlink:href="#p0" transform="translate(460,0)" id="use3" />
  </g>
</svg>

虽然Opera仍然没有运气,但这次我对IE9和Safari也不满意。但我相信它应该可以用于Opera和Safari,只有我做了一些不正确的事情。

答案 1 :(得分:2)

这似乎是根据规范:

  

对于支持使用CSS设置样式的用户代理,概念性很深   将引用的元素克隆到非暴露的DOM树中   复制CSS级联产生的任何属性值([CSS2],   第6章)关于引用的元素及其内容。 CSS2选择器   可以应用于原始(即引用的)元素,因为   它们是正式文件结构的一部分。 CSS2选择器不能   应用于(概念上)克隆的DOM树,因为它的内容   不属于正式文件结构。

我尝试了一些使用的解决方法:hover和/或[]属性选择器语法,运气不好但是可能有解决方案。

答案 2 :(得分:1)

也许这可以提供帮助:https://codepen.io/AmeliaBR/post/customizable-svg-icons-css-variables

    <svg  xmlns="http://www.w3.org/2000/svg" 
     viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"
     class="raw">
  <g id="palette">
  <path d="M5,90
           C5,45 40,-5 75,10 
           C110,25 80,95 60,95
           C50,95 50,75 30,75
           C20,75 17,95 12,95
           C10,95 5,95 5,90 Z"/>
    <g  style="fill:currentColor;">
  <path d="M30,50 
           c-10,0 -20,20 -5,15
           s15,-15 5,-15z
           "/>
  <path  d="M45,30 
           c-10,0 -15,15 -5,15
           s10,-15 5,-15z
           "/>
  <path  d="M70,20 
           c-10,0 -20,15 -5,15
           s10,-15 5,-15z
           "/>
  <path  d="M75,45 
           c-10,0 -20,15 -5,15
           s15,-15 5,-15z
           "/>
  <path  d="M65,65 
           c-10,0 -15,25 -5,20
           s10,-20 5,-20z"/>
    </g>
  </g>
</svg>
<svg class="icon-style-A">
    <use xlink:href="#palette"/>
</svg>

<svg class="icon-style-B">
    <use xlink:href="#palette"/>
</svg>

<svg class="icon-style-C">
    <use xlink:href="#palette"/>
</svg>

    svg {
  display:inline-block;
  height:100px; 
  width:100px;
  margin:10px;
  border:1px solid;
  background:#eee;
}
svg.raw {
/* Default styles for the initial SVG.
 * Because they are defined on the <svg>,
 * not the individual graphics elements, 
 * they will NOT be inherited by the <use> references.
 */
  fill:rgba(255,250,220,0.4);
  stroke: rgba(0,0,0,0.7);
  stroke-width:2;
}
svg.icon-style-A {
/* Set the fill, stroke, and color properties to be 
   inherited by the <use> element:
 */
  fill:burlywood;
  color:blueviolet;
  stroke:#222; 
  stroke-width:0.5px;
}
svg.icon-style-B {
/* Set the color properties:
 */
  fill:blanchedalmond;
  color:lavender;
  stroke:white;
  stroke-width:1px;
/* set some icon styles on the <svg> itself: */
  background:aliceblue;
  border-radius:20%;
  border:none;
  box-shadow:royalblue 0 0 2px;
}
svg.icon-style-C {
/* Set the color properties:
 */
  fill:beige;
  color:green;
  stroke:#aaa; 
  stroke-width:1.5px;
/* icon styles for the <svg> itself: */
  background:#222;
  border-radius:10%;
  border:solid gray;
}

不是很灵活,但它适用于我的项目。