SVG USE 元素和 :hover 样式
Posted
技术标签:
【中文标题】SVG USE 元素和 :hover 样式【英文标题】:SVG USE element and :hover style 【发布时间】:2012-11-20 08:09:17 【问题描述】:我正在尝试使用 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"
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>
我希望它以这样一种方式工作,即当用户将鼠标指针放在嵌入元素上时,其具有“活动”类的内部元素将改变其样式。当我直接从<defs>
嵌入一个形状并将CSS 类应用于嵌入它的<use>
时,它就起作用了。但它不适用于通过 <use>
嵌入的组内的任何类或 ID。
如何解决?
或者也许有更好的方法来做到这一点?
当用户将鼠标悬停在嵌入对象中时,我只需要更改该特定部分,而不是整个组。这是因为该组的不同部分会应用不同的样式,并且在鼠标悬停时需要进行不同的更改。
编辑:我想得到什么
我想要的是一种将 <defs>
中的“库对象”嵌入到我的 SVG 文档中许多不同位置的方法。该对象的某些部分需要使用 CSS 中的自定义颜色设置样式,因为我需要在不更改库对象代码的情况下轻松自定义这些颜色。
然后,当鼠标指针位于此类“活动”对象上方时,我需要通过对其部分进行不同样式设置来向用户发出信号:当鼠标指针悬停在可点击区域上方时,这里和那里的一些明亮轮廓可以显示可点击区域的形状。
不幸的是,我无法将样式应用于 <use>
元素的子元素,因为它们不是 DOM 中 <use>
的子元素(正如其他人已经提到的那样)。我可以对 <defs>
部分中的元素应用一些样式,因为它们在 DOM 中并且可以使用 CSS 选择器进行寻址,但是它们不能悬停,因为它们是不可见的,所以对它们应用:hover
伪类是行不通的。如果将此类应用于<use>
,它也不起作用,因为这样我就无法子选择正确的子元素(它们不是<use>
的子元素)。所以我没有任何钩子可以将那些:hover
伪类应用到。
也许我的问题还有其他解决方案?
【问题讨论】:
【参考方案1】:您无法处理通过 use 引用的元素。 The specs说:
对于支持使用 CSS 进行样式设置的用户代理,将引用元素概念性地深度克隆到未公开的 DOM 树中还会复制引用元素上的 CSS 级联([CSS2],第 6 章)产生的任何属性值,并且它的内容。 CSS2 选择器可以应用于原始(即引用的)元素,因为它们是正式文档结构的一部分。 CSS2 选择器不能应用于(概念上)克隆的 DOM 树,因为它的内容不是正式文档结构的一部分。
尽管如此,Firefox 支持寻址通过使用虫洞包含的“虚拟”元素。所有其他浏览器都没有。
如果您为引用的元素指定填充/描边值currentColor
,然后在悬停时更改<use>
元素的color
属性,浏览器还支持更改填充或描边颜色。像这样:
<svg version="1.1" 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" 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 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 应该可以,只是我做了一些不是 100% 正确的事情。
【讨论】:
你是对的。它在 Opera 中不起作用。我已经稍微更新了我的问题,以进一步描述我想要得到的东西。 为了完整起见(因为我刚刚在这里重定向了一个副本):除了使用currentColor
,您还可以使用inherit
来强制填充或描边值使用来自<use>
元素。这可以为您提供更大的灵活性:您可以修改主填充颜色、描边颜色和对比颜色(使用currentColor
)。一旦 CSS 变量被广泛实施,they will enable complete customization.【参考方案2】:
这似乎符合规范:
对于支持使用 CSS 进行样式设置的用户代理,概念深度 将引用的元素克隆到非公开的 DOM 树中 复制由 CSS 级联 ([CSS2], 第 6 章)关于引用的元素及其内容。 CSS2 选择器 可以应用于原始(即引用的)元素,因为 它们是正式文件结构的一部分。 CSS2 选择器不能 应用于(概念上)克隆的 DOM 树,因为它的内容 不是正式文档结构的一部分。
我尝试了一些使用 use:hover 和/或 [] 属性选择器语法的变通方法,但运气不佳,但那里可能有解决方案。
【讨论】:
对不起,在写我的答案时没有认出你的答案。引用了相同的规格段落... NP。我没有想到 currentColor 是一个很好的部分解决方案。【参考方案3】:也许这会有所帮助: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;
不是很灵活,但它适用于我的项目。
【讨论】:
以上是关于SVG USE 元素和 :hover 样式的主要内容,如果未能解决你的问题,请参考以下文章
css 当中如何实现一个元素的hover, focus 状态改变其他元素的样式