是否可以部分基于某些值填充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组件进行复制。