javascript - 使用评级系统设置半图标
问题描述
我构建了一个组件,它基本上是一个评级系统,允许您根据下拉列表添加更多图标。
我想知道是否有办法制作半星,我查看了互联网上的旧代码,但没有任何更新。任何帮助不胜感激
import React, { useState } from 'react'
import {FaStar} from "react-icons/all";
import './Rater.css'
const Rater = () => {
const [rating, setRating] = useState(null)
const [hover, setHover] = useState(null)
const [value] = useState(100)
const [iconValue, setIconValue] = useState(5)
return (
<div>
<select onChange={(e) =>
{setIconValue(Number(e.target.value))}}>
{ Array.from(new Array(value),(value, index) =>
index + 1).map(value => <option
key={value} value={value}>{value}</option>) }
</select>
<h1> Select Amount of Icons </h1>
{[... Array(iconValue)].map((icon, i) => {
const value = i + 1
return (
<label>
<input type='radio'
name='rating'
value={value}
onClick={() => setRating(value)}
/>
<FaStar classname='star'
color={value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
size={100}
onMouseEnter={() => setHover(value)}
onMouseLeave={() => setHover(null)}
/>
</label>
)
})}
</div>
)
}
export default Rater
解决方案
我查看了您的代码,您的星形图标在 SVG 中。您可以编写渐变模板并添加fill: url(#id)
到您要更改的星号
.linear-gradient-template {
width: 0;
height: 0;
}
<svg class="linear-gradient-template">
<linearGradient id="orange_grey" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="50%" style="stop-color: rgb(255, 193, 7)"></stop>
<stop offset="50%" style="stop-color: rgb(228, 229, 233)"></stop>
</linearGradient>
</svg>
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 576 512" class="one,star" color="#ffc107" size="100" height="100" width="100" xmlns="http://www.w3.org/2000/svg" style="color: rgb(255, 193, 7);">
<path style="fill: url(#orange_grey)" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path>
</svg>
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 576 512" class="one,star" color="#ffc107" size="100" height="100" width="100" xmlns="http://www.w3.org/2000/svg" style="color: rgb(255, 193, 7);">
<path style="fill: url(#orange_grey)" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path>
</svg>
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 576 512" class="one,star" color="#ffc107" size="100" height="100" width="100" xmlns="http://www.w3.org/2000/svg" style="color: rgb(255, 193, 7);">
<path style="fill: url(#orange_grey)" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path>
</svg>
import React, { useState } from 'react'
import {FaStar} from "react-icons/all";
import './Rater.css'
const Rater = () => {
const [rating, setRating] = useState(null)
const [hover, setHover] = useState(null)
const [value] = useState(100)
const [iconValue, setIconValue] = useState(5)
const size = 100
return (
<div id="start-wrap">
<svg className="linear-gradient-template">
<linearGradient id="orange_red" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="50%" style={{stopColor: 'rgb(255, 193, 7)'}}></stop>
<stop offset="50%" style={{stopColor: 'rgb(228, 229, 233)'}}></stop>
</linearGradient>
</svg>
<select onChange={(e) =>
{setIconValue(Number(e.target.value))}}>
{ Array.from(new Array(value),(value, index) =>
index + 1).map(value => <option
key={value} value={value}>{value}</option>) }
</select>
<h1> Select Amount of Icons </h1>
{[... Array(iconValue)].map((icon, i) => {
const value = i + 1
return (
<label>
<input type='radio'
name='rating'
value={value}
onClick={() => setRating(value)}
/>
<FaStar
className='star'
color={value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
size={size}
onMouseEnter={(e) => setHover(value)}
onMouseLeave={() => {
let svgDom = document.getElementsByClassName('star')[i]
let pathDom = svgDom.children[0]
pathDom.style.fill = ''
setHover(null)
}}
onMouseMove={e => {
let svgDom = document.getElementsByClassName('star')[i]
let pathDom = svgDom.children[0]
if(e.pageX - svgDom.getBoundingClientRect().left <= size / 2){
pathDom.style.fill = 'url(#orange_red)'
} else {
pathDom.style.fill = ''
}
}}
/>
</label>
)
})}
</div>
)
}
export default Rater
以上,我修改了你的代码,并不完美,你可以根据自己的需要修改。
推荐阅读
- c# - Json 到 C# 没有正确反序列化货币符号
- angular - Angular 6 反应形式示例在 plunker 上失败
- angular - ngFor 如何根据键值将值包装在 div 容器中
- vue.js - 页面更改时无法在 Vuejs 中查看来自 Janus-Gateway 的流
- python - 总结两个文本文件并在python中创建一个新文件
- python - 如何将字符串中的连续字母和连续数字分别合并到列表中?
- c# - 为我的类属性值应用自定义格式的最佳方法是什么?
- symfony - 自动装配 TagAwareCache 并注入服务
- ruby-on-rails - 如何以错误的顺序检查括号的有效性
- wordpress - 如何提交在远程服务器上所做的 git 更改