I currently have a rating system that produces 5 stars that can show half values. I did this by using FontAwesome's Half Stars and did some CSS tricks to make them look like one star. But I was thinking of increasing my React and CSS knowledge by coming up with a way to show only half of an SVG icon. So instead of using the Half Stars, I could use whatever Icon the user wanted, and it would only show 50% of the Icon for example if you wanted to give a 3.5 rating.
Q: Can you show only half of an Icon and somehow know if the user is clicking on one side or the other?
Here is the code I have currently that uses the HalfStars for a little bit of reference
import React, { useState } from 'react'
import { FaRegStarHalf, FaStarHalf } from 'react-icons/fa'
import './styles/Rater.css'
const Rater = ({ iconCount }) => {
const [rating, setRating] = useState(null)
const [hover, setHover] = useState(null)
// check if user has set a rating by clicking a star and use rating to determine icons
const Star = rating ? FaStarHalf : FaRegStarHalf
return (
<div>
{[...Array(iconCount), ...Array(iconCount)].map((icon, i) => {
const value = (i + 1) / 2
return (
<label>
<input
type='radio'
name='rating'
value={value}
onClick={() => {
console.log(`value => `, value)
return setRating(value)
}}
/>
<div className='star-container'>
<div>
<Star
className={i % 2 ? 'star-left' : 'star'}
color={value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
onMouseEnter={() => setHover(value)}
onMouseLeave={() => setHover(null)}
/>
</div>
</div>
</label>
)
})}
</div>
)
}
export default Rater
I have written a code to get you the idea; If you click on the right side of the star, its color changes to blue and if you click on the left side, its color changes to gold. Also, it's better to not use stopPropagation
and check e.target
of the event.
const starIcon = document.getElementById("star");
const icon = document.getElementById("icon");
starIcon.onclick = e => {
starIcon.style.color = "blue";
e.stopPropagation();
};
icon.onclick = e => {
starIcon.style.color = "gold";
}
i {
clip-path: inset(0 0 0 50%);
color: gold;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" rel="stylesheet">
</head>
<body>
<span id="icon"><i id="star", class="fas fa-star"></i></span>
</body>
</html>