SVG 将渐变修改为与 "use" 重用的元素
SVG modifying gradient to an element that is reused with "use"
我正在使用一个简单的 SVG 三角形路径,它是 fill 通过 CSS 使用对 SVG 渐变 的引用编辑的].
SVG:
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="gradient">
<stop offset="0%" />
<stop offset="100%" />
</linearGradient>
<polygon id="triangle" points="0,0 100,0 0,66" />
</svg>
CSS:
#triangle {
fill: url(#gradient);
}
在渐变中使用的颜色有更多自由度,并且
从标记中获取颜色 我选择使用 CSS custom properties (aka CSS Variables)
CSS:
#gradient stop:first-child {
stop-color: var(--color-stop);
}
#gradient stop {
stop-color: var(--color-stop2);
}
到目前为止还不错,问题是我想重新使用那个三角形并给它另一种颜色。
覆盖 CSS 变量无效!
https://codepen.io/Type-Style/pen/gNYpjL
// nothing in js this time
svg {width: 250px; height:200px;}
:root {
--color-stop: orange;
--color-stop2: red;
}
.second { /* has no effect */
--color-stop: lime;
--color-stop2: green;
}
#gradient stop:first-child {
stop-color: var(--color-stop);
}
#gradient stop {
stop-color: var(--color-stop2);
}
#triangle {
fill: url(#gradient);
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="gradient">
<stop offset="0%" />
<stop offset="100%" />
</linearGradient>
<polygon id="triangle" points="0,0 100,0 0,66" />
</svg>
<svg class="second" viewBox="0 0 100 100">
<use class="use-triangle" href="#triangle" />
</svg>
预期结果:
我希望用不同的方式着色第二个三角形。
结果:
但是好像一旦用了渐变,就没办法modifying/overwriting了。
感觉渐变只取直接分配给它的值,使用后无法更改。
这可能是由于引用 ID 的填充用法的性质,但我不确定
我尝试过的/功劳:
我检查了 SVG gradient using CSS,这是我从中获取和修改示例的地方。 (感谢@Maciej-Kwas)
此外,我知道您可以 inherit fill and use currentColor 为 "used" 的元素提供更多颜色。但到目前为止,我还无法让它与渐变一起工作。
不满意的解决方法:
因为我的目标是将颜色保留在标记之外,所以我可以将 svg 移动到 css 内联作为数据 Uri,就像这样:
fill: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><linearGradient id='grad'><stop offset='0%' stop-color='%23ff00cc'/><stop offset='100%' stop-color='%23333399'/></linearGradient></svg>#grad")
有关这篇文章的重要功劳:https://fvsch.com/svg-gradient-fill/
但是因为这只适用于 Firefox,而且看起来很老套。
结束语:
请问有没有其他解决办法。并且想首先详细了解为什么它不能像我预期的那样工作。
我不确定您是否正在寻找通用解决方案,但对于这种特殊情况,您可以使用纯 CSS 来达到相同的效果。
下面的技巧很有效,因为渐变方向是水平的:
:root {
--c1: orange;
--c2: red;
}
.second {
--c1: lime;
--c2: green;
}
.triangle {
width: 200px;
height: 132px;
display: inline-block;
overflow: hidden;
position: relative;
}
.triangle:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to right, var(--c1), var(--c2));
transform: skewY(-33.42deg); /* arctan(132/200)*/
transform-origin: left;
}
<div class="triangle">
</div>
<div class="triangle second">
</div>
您还可以考虑 clip-path
,这样可以更轻松地定义任何类型的渐变,但您需要注意浏览器支持。您可能还会注意到多边形的语法与 SVG 中的语法几乎相似,因此您也可以考虑任何一种形状。
:root {
--c1: orange;
--c2: red;
}
.second {
--c1: lime;
--c2: green;
}
.triangle {
width: 200px;
height: 132px;
display: inline-block;
background: linear-gradient(65deg, var(--c1), var(--c2));
-webkit-clip-path:polygon(0 0,100% 0,0 100%);
clip-path:polygon(0 0,100% 0,0 100%);
}
<div class="triangle">
</div>
<div class="triangle second">
</div>
两个观察结果:
您需要定义 2 个渐变并选择带有变量的渐变:fill: var(--grd);
您没有填写需要重复使用的<polygon>
。您填写 <use>
元素。
希望对您有所帮助。
svg {width: 250px; height:200px;border:1px solid}
:root {
--grd: url(#gradient);
}
.second{--grd: url(#gradient2);}
use {
fill: var(--grd);
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="orange"/>
<stop offset="100%" stop-color="red" />
</linearGradient>
<linearGradient id="gradient2">
<stop offset="0%" stop-color="lime"/>
<stop offset="100%" stop-color="green" />
</linearGradient>
<polygon id="triangle" points="0,0 100,0 0,66" />
</defs>
<use class="use-triangle" xlink:href="#triangle" />
</svg>
<svg class="second" viewBox="0 0 100 100">
<use class="use-triangle" xlink:href="#triangle" />
</svg>
我正在使用一个简单的 SVG 三角形路径,它是 fill 通过 CSS 使用对 SVG 渐变 的引用编辑的].
SVG:
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="gradient">
<stop offset="0%" />
<stop offset="100%" />
</linearGradient>
<polygon id="triangle" points="0,0 100,0 0,66" />
</svg>
CSS:
#triangle {
fill: url(#gradient);
}
在渐变中使用的颜色有更多自由度,并且 从标记中获取颜色 我选择使用 CSS custom properties (aka CSS Variables)
CSS:
#gradient stop:first-child {
stop-color: var(--color-stop);
}
#gradient stop {
stop-color: var(--color-stop2);
}
到目前为止还不错,问题是我想重新使用那个三角形并给它另一种颜色。 覆盖 CSS 变量无效! https://codepen.io/Type-Style/pen/gNYpjL
// nothing in js this time
svg {width: 250px; height:200px;}
:root {
--color-stop: orange;
--color-stop2: red;
}
.second { /* has no effect */
--color-stop: lime;
--color-stop2: green;
}
#gradient stop:first-child {
stop-color: var(--color-stop);
}
#gradient stop {
stop-color: var(--color-stop2);
}
#triangle {
fill: url(#gradient);
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="gradient">
<stop offset="0%" />
<stop offset="100%" />
</linearGradient>
<polygon id="triangle" points="0,0 100,0 0,66" />
</svg>
<svg class="second" viewBox="0 0 100 100">
<use class="use-triangle" href="#triangle" />
</svg>
预期结果:
我希望用不同的方式着色第二个三角形。
结果:
但是好像一旦用了渐变,就没办法modifying/overwriting了。 感觉渐变只取直接分配给它的值,使用后无法更改。 这可能是由于引用 ID 的填充用法的性质,但我不确定
我尝试过的/功劳:
我检查了 SVG gradient using CSS,这是我从中获取和修改示例的地方。 (感谢@Maciej-Kwas)
此外,我知道您可以 inherit fill and use currentColor 为 "used" 的元素提供更多颜色。但到目前为止,我还无法让它与渐变一起工作。
不满意的解决方法:
因为我的目标是将颜色保留在标记之外,所以我可以将 svg 移动到 css 内联作为数据 Uri,就像这样:
fill: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><linearGradient id='grad'><stop offset='0%' stop-color='%23ff00cc'/><stop offset='100%' stop-color='%23333399'/></linearGradient></svg>#grad")
有关这篇文章的重要功劳:https://fvsch.com/svg-gradient-fill/
但是因为这只适用于 Firefox,而且看起来很老套。
结束语:
请问有没有其他解决办法。并且想首先详细了解为什么它不能像我预期的那样工作。
我不确定您是否正在寻找通用解决方案,但对于这种特殊情况,您可以使用纯 CSS 来达到相同的效果。
下面的技巧很有效,因为渐变方向是水平的:
:root {
--c1: orange;
--c2: red;
}
.second {
--c1: lime;
--c2: green;
}
.triangle {
width: 200px;
height: 132px;
display: inline-block;
overflow: hidden;
position: relative;
}
.triangle:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to right, var(--c1), var(--c2));
transform: skewY(-33.42deg); /* arctan(132/200)*/
transform-origin: left;
}
<div class="triangle">
</div>
<div class="triangle second">
</div>
您还可以考虑 clip-path
,这样可以更轻松地定义任何类型的渐变,但您需要注意浏览器支持。您可能还会注意到多边形的语法与 SVG 中的语法几乎相似,因此您也可以考虑任何一种形状。
:root {
--c1: orange;
--c2: red;
}
.second {
--c1: lime;
--c2: green;
}
.triangle {
width: 200px;
height: 132px;
display: inline-block;
background: linear-gradient(65deg, var(--c1), var(--c2));
-webkit-clip-path:polygon(0 0,100% 0,0 100%);
clip-path:polygon(0 0,100% 0,0 100%);
}
<div class="triangle">
</div>
<div class="triangle second">
</div>
两个观察结果:
您需要定义 2 个渐变并选择带有变量的渐变:
fill: var(--grd);
您没有填写需要重复使用的
<polygon>
。您填写<use>
元素。
希望对您有所帮助。
svg {width: 250px; height:200px;border:1px solid}
:root {
--grd: url(#gradient);
}
.second{--grd: url(#gradient2);}
use {
fill: var(--grd);
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0%" stop-color="orange"/>
<stop offset="100%" stop-color="red" />
</linearGradient>
<linearGradient id="gradient2">
<stop offset="0%" stop-color="lime"/>
<stop offset="100%" stop-color="green" />
</linearGradient>
<polygon id="triangle" points="0,0 100,0 0,66" />
</defs>
<use class="use-triangle" xlink:href="#triangle" />
</svg>
<svg class="second" viewBox="0 0 100 100">
<use class="use-triangle" xlink:href="#triangle" />
</svg>