使用Css部分填充SVG图标



是否可以部分基于某些值填充svg图标?用例:星级

svg{
fill: red;
}
<!DOCTYPE html>
<html lang="en">
<title></title>
<script src="https://unpkg.com/feather-icons"></script>
<body>
<!-- example icon -->
<i data-feather="star"></i>
<i data-feather="star"></i>
<i data-feather="star"></i>
<script>
feather.replace()
</script>
</body>
</html>

假设您不能直接编辑原始路径,您可以操作SVG的dom插入一个带有ID的渐变标签,然后在CSS中使用fill : url(#gradient);引用它。这看起来有点古怪,但它有效:

svg.full {
fill:red;
}
svg#half {
fill : url(#gradient);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<script src="https://unpkg.com/feather-icons"></script>
</head>
<body>
<!-- example icon -->
<i class="full" data-feather="star"></i>
<i id="half" data-feather="star"></i>
<i data-feather="star"></i>

<script type="text/javascript">
feather.replace();

// create the defs SVG tag
// it is important to use createElementNS in that case
const defs = document.createElementNS("http://www.w3.org/2000/svg", 'defs');
defs.innerHTML = '<linearGradient id="gradient"><stop offset="50%" stop-color="#F00"></stop><stop offset="50%" stop-color="transparent" ></stop></linearGradient>';

// Here I'm targeting only the middle start by ID
// You should modify the code to target all half-stars
document.getElementById('half').append(defs);

</script>

</body>
</html>

PS:通过玩<stop>标签属性,您可以获得一些原始效果。

您可以在一个SVG中完成

  • 我放弃了字体真棒图标
  • 搜索";星形;在上的7000多个图标中https://iconmeister.github.io/(第一次加载需要一分钟(
  • 选择最佳d-路径的星形图标(Clarity Iconset:cl-social-star-solid(
  • 只复制了d路径
  • 在中编辑d路径https://yqnn.github.io/svg-path-editor/到100x100视图框/网格
  • 通过在路径前加上M0 0h100v100h-100v-100使其成为
  • 0 0 300 100视图框中创建了一个新的SVG文件以容纳三星。。见下文
  • 添加了背景矩形设置金色颜色等级width="50%"
  • 使用3颗反向恒星,每颗都有x偏移
  • 添加6个矩形覆盖所有半星
  • 在每个";"半星">
    (单击在此SO片段中有效,但SO添加了很长的延迟(

概念证明

<svg viewBox="0 0 300 100" width="500px">
<rect id="rating" width="50%" fill="gold" height="100%" />
<path id="star" fill="green" 
d="M0 0h100v100h-100v-100m91 42a6 6 90 00-4-10l-22-1a1 1 90 01-1 
0l-8-21a6 6 90 00-11 0l-8 21a1 1 90 01-1 1l-22 1a6 6 90 00-4 
10l18 14a1 1 90 010 1l-6 22a6 6 90 008 6l19-13a1 1 90 011 0l19
13a6 6 90 006 0a6 6 90 002-6l-6-22a1 1 90 010-1z"/>
<use href="#star" x="100" />
<use href="#star" x="200" />
<rect id="c" width="16.66%" height="100%" fill="transparent" stroke="red" 
onclick="console.log(this)" />
<use href="#c" x="50" />
<use href="#c" x="100" />
<use href="#c" x="150" />
<use href="#c" x="200" />
<use href="#c" x="250" />
</svg>

星级评定组件<star-rating stars=N >

你不想手工创建所有这些SVG。。。几行JavaScript可以为任意数量的星创建SVG

在此处使用W3C标准Web组件,因为它在该页面中运行,并且不像React组件那样复杂。

https://developer.mozilla.org/en-US/docs/Web/Web_Components

  • 不使用<use>,只使用x偏移量复制所有路径和矩形
  • 鼠标悬停事件设置背景%颜色
  • 单击显示单击的半星(0+(的索引
  • 评分可以设置为百分比;document.querySelector('[stars="5"]').rating="90%"(4.5颗星(
  • 可能需要为您的用例做额外的工作

所有必需的HTML&JavaScript:

<star-rating stars=5 rating="3.5"
bgcolor="green" nocolor="grey" color="gold"></star-rating>
<star-rating stars=7 rating="50%"
bgcolor="rebeccapurple" nocolor="beige" color="goldenrod"></star-rating>
<script>
document.addEventListener("click", (evt) => console.log(evt.target.getAttribute("n")))
customElements.define("star-rating", class extends HTMLElement {
set rating( rate ) {
if (!String(rate).includes("%")) rate = Number(rate) / this.stars * 100 + "%";
this.querySelector("#rating").setAttribute("width", rate);
}
connectedCallback() {
let { bgcolor, stars, nocolor, color, rating } = this.attributes;
this.stars = ~~stars.value || 5;
this.innerHTML = 
`<svg viewBox="0 0 ${this.stars*100} 100" style="cursor:pointer;width:300px">`
+ `<rect width="100%" height="100" fill="${nocolor.value}"/>`
+ `<rect id="rating"  height="100" fill="${color.value}"  />`
+ Array(  this.stars     ).fill()
.map((i, n) => `<path fill="${bgcolor.value}" d="M${ n*100 } 0h102v100h-102v-100m91 42a6 6 90 00-4-10l-22-1a1 1 90 01-1 0l-8-21a6 6 90 00-11 0l-8 21a1 1 90 01-1 1l-22 1a6 6 90 00-4 10l18 14a1 1 90 010 1l-6 22a6 6 90 008 6l19-13a1 1 90 011 0l19 13a6 6 90 006 0a6 6 90 002-6l-6-22a1 1 90 010-1z"/>`)
.join("")
+ Array(  this.stars * 2 ).fill()
.map((i, n) => `<rect x="${ n*50 }" n="${n}" opacity="0" width="50" height="100"`
+ ` onclick="dispatchEvent(new Event('click'))" `
+ ` onmouseover="this.closest('star-rating').rating = ${(n+1)/2}"/>`)
.join("") 
+ "</svg>";
this.rating = rating.value;
}
});
</script>

备注

  • 本机<star-rating>组件(也称为自定义元素,因为不涉及shadowDOM(具有零依赖项
    • 无库
    • 无外部SVG
  • 本机组件不是自关闭标记,必须包含连字符,因此表示法为:<star-rating></star-rating>
  • 将星号更改为M0 0h102v100h-102v-100(2像素重叠(,以解决SVG舍入问题
  • 所有框架都支持。。。除了

    React还不支持这个现代W3C Web Components标准。

    React得分仅71%https://custom-elements-everywhere.com/

    所有其他框架(Angular、Vue、Svelte(都100%支持

    您必须做一些额外的工作来处理React中的本地DOM元素和事件;但是自定义元素并不复杂。。它创建SVG;应该很容易作为React组件进行复制。

    最新更新