解决评价打分组件 SVG 半颗星的方法
对于一个内容服务的网站来说评价打分也是很重要的一部分,它有利于分析用户对我们的内容的喜好程序。最近,我们团需要为一个项目实现一个星级评价的组件,需求如下:
- 性能(不能用图片)
- 可调整的大小
- 可访问性
- 小数位打分(如:
3.5或3.2) - 使用 css 就可以直接控制样式
要达到上面的要求,经常调研,最终选择了 SVG 方案。
任务
下图是我们最终想要的效果:

我们主要的工作就是让星星可以改变其颜色,描边,大小,还可以显示半颗星星。
实现
在实现之前,我们需要有一个基础 SVG 结构,如下所示:
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="..."/>
</svg>
添加 aria-label
添加 aria-label 可以使用读屏器用户能够访问这一信息。
<p aria-label="Rating is 4.5 out of 5">
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="..."/>
</svg>
</p>
aria-label属性用来给当前元素加上的标签描述,接受字符串作为参数。是用不可视的方式给元素加label(如果被描述元素存在真实的描述元素,可使用aria-labelledby属性作为来绑定描述元素和被描述元素来代替)。
如何重用 SVG
我们可以把上面的 SVG 标签复制五次,或者提取path数据并保存在某个地方,然后在不重复代码的情况下重新使用它。我们选择后者。
首先,我们需要创建一个宽度和高度为零的 SVG,这样它就不会保留空间。
<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Content -->
</svg>
在该 SVG 中,我们需要在<symbol>元素中包含path数据。根据 MDN:
symbol 元素用于定义图形模板对象,可以通过
<use>元素来实例化。
<symbol>里面的内容与图标的内容相同。另外,添加一个 id 也很重要,这样我们以后就可以引用这个 symbol 。
<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" id="star">
<path d="..."/>
</symbol>
</svg>
有了这个设置,我们现在可以用<use>元素来重用这个symbol。做法就是使用id作为href属性的值。
<p class="c-rate">
<svg class="c-icon" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon" width="32" height="32">
<use href="#star"></use>
</svg>
</p>
星星的样式
有了上面的星星结构,我们现在来添加样式:
<p class="c-rate">
<svg class="c-icon active" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon active" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon active" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon active" width="32" height="32">
<use href="#star"></use>
</svg>
<svg class="c-icon" width="32" height="32">
<use href="#star"></use>
</svg>
</p>
CSS 样式:
.c-icon {
--star-active: #fece3c;
--star-inactive: #6c6962;
fill: var(--star-inactive);
}
.c-icon.active {
fill: var(--star-active);
}
运行后的结果:

半颗星
使用 SVG 后做半颗星就很容易,有两个很好的解决方案。第一个是使用<masks>,第二个是使用 SVG 渐变。
使用 <masks>
使用 masks 的目的是模拟擦除星星的一部分并将另一部分涂成半透明颜色的效果。

在上图中,有一个正方形和一个星星。它们的交集就是我们想要的结果。
做法如下:
- 创建一个可重用的 SVG 模板;
- 添加一个
<mask>元素,位置为x=50%; - 将 mask 应用到星星上。
<!-- The reusable SVG template -->
<svg viewBox="0 0 32 32" id="star">
<defs>
<mask id="half">
<rect x="50%" y="0" width="32" height="32" fill="white" />
</mask>
<symbol viewBox="0 0 32 32" id="star">
<path d="..." />
</symbol>
</defs>
</svg>
<svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
<use href="#star" mask="url(#half)" fill="green"></use>
</svg>
问题是,当一颗半透明的星星被遮住时,我们如何才能显示它呢? 好吧,多亏了 SVG,我们可以在 <mask> 中包含多个元素。
<mask id="half"> <rect x="0" y="0" width="32" height="32" fill="white" /> <rect x="50%" y="0" width="32" height="32" fill="black" /> </mask>
在 mask 中,白色元素表示我们想要显示的内容,黑色元素表示我们想要隐藏的内容。结合在一起时,我们可以创建一个cut-out effect效果。

注意,白色矩形被定位在0,0点,而黑色矩形被定位在50%,0。下面是它的效果:

涂写的部分代表最终结果,半颗星。 现在,你的可能在想,如何添加另一个半透明的星星以使其更清晰?
通过使用比纯黑更浅的颜色,我们将得到一个半透明的效果。这意味着目前被隐藏的区域将有一个浅色的星形颜色。
<mask id="half"> <rect x="0" y="0" width="32" height="32" fill="white" /> <rect x="50%" y="0" width="32" height="32" fill="grey" /> </mask>

到这,我们回顾一下完整的 SVG 标签。
<svg style="width: 0; height: 0;" viewBox="0 0 32 32">
<defs>
<mask id="half">
<rect x="0" y="0" width="32" height="32" fill="white" />
<rect x="50%" y="0" width="32" height="32" fill="grey" />
</mask>
<symbol viewBox="0 0 32 32" id="star">
<path d="..." />
</symbol>
</defs>
</svg>
<p class="c-rate">
<svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
<use href="#star" mask="url(#half)" fill="green"></use>
</svg>
<!-- 4 more stars -->
</p>
这样,我们就有了一个部分填充的恒星。这个解决方案的绝妙之处在于,我们不需要提供两种色调, mask 会起作用的:

完整代码:点击链接
第一种方法到这就介绍完了,我们来看第二种方法。
带有 SVG 渐变的半星
与mask类似,我们需要在<defs>元素中定义一个渐变。
<svg style="width: 0; height: 0;" viewBox="0 0 32 32">
<defs>
<linearGradient id="half" x1="0" x2="100%" y1="0" y2="0">
<stop offset="50%" stop-color="#f7efc5"></stop>
<stop offset="50%" stop-color="#fed94b"></stop>
</linearGradient>
</defs>
</svg>
注意,我们有两个色块,第一个代表前半部分,第二个代表浅色阴影。在这个解决方案中,我们需要手动提供两种颜色。

<p class="c-rate">
<svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
<use href="#star" fill="url(#half)"></use>
</svg>
</p>
事例地址:点击链接
轮廓样式
接下来我们给星星做个轮廓,这样看起来会更立体点。

SVG Mask 解决轮廓样式的问题
要添加描边,我们只需要在 SVG 元素中添加stroke。这将很好地工作全星。然而,对于部分的,它将被切断,因为掩码。这对完整的星星来说是很好的。然而,对于半颗,由于mask的原因,它将被遮住。

为了解决这个问题,我们需要另一个星形轮廓。可以通过复制<use>元素并删除它的 mask 来实现这一点。
<p class="c-rate">
<svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
<use href="#star" mask="url(#half)" fill="green"></use>
<use href="#star" fill="none" stroke="grey"></use>
</svg>
</p>
注意,我们有两个<use>元素。一个带mask的,一个只有 stroke 的。这就是使用 SVG masks 实现轮廓样式的方法。
事例地址:点击链接
SVG 渐变实现轮廓样式
对于渐变解决方案,我们不需要复制图标,因为没有mask 。我们需要做的是添加一个stroke,它就完成了。
<svg style="width: 0; height: 0;" viewBox="0 0 32 32">
<defs>
<linearGradient id="half" x1="0" x2="100%" y1="0" y2="0">
<stop offset="50%" stop-color="#f7efc5"></stop>
<stop offset="50%" stop-color="#fed94b"></stop>
</linearGradient>
</defs>
</svg>
<p class="c-rate">
<svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
<use href="#star" fill="url(#half)" stroke="grey"></use>
</svg>
</p>
事例地址:点击链接
大小
通过使用 CSS 变量并确保 SVG 具有正确的viewBox属性,我们可以轻松地调整它们的大小。
.c-icon {
width: var(--size, 24px)
height: var(--size, 24px);
}
.c-icon--md {
--size: 40px;
}
.c-icon--lg {
--size: 64px;
}
以上关于解决评价打分组件 SVG 半颗星的方法的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 解决评价打分组件 SVG 半颗星的方法

微信
支付宝