JSFiddle - React, Tailwind, and code Playground
HTML
<div class="stars">
<div class="stars__inner">
<div class="stars__data">
<svg id="rating" width="130pt" height="28pt" viewBox="0 0 130 28" xmlns="http://www.w3.org/2000/svg">
<!-- СОЗДАЕМ МАСКУ-->
<mask id="mask">
<rect fill="white" width="100%" height="100%" />
<path fill="black" d="M0 0h130v28H0V0m11.95 3.62c-.45 2.45-1.38 4.78-2.56 6.97-2.72-.12-5.44-.12-8.16-.05l.32 2c1.86 1.37 3.7 2.75 5.42 4.29-.35 3.06-1.83 5.9-1.61 9.03 2.71-1.21 5.21-2.82 7.66-4.48 2.43 1.72 4.67 4.05 7.75 4.49-.31-3.04-1.55-5.91-1.61-8.99 2.17-1.71 5.9-2.74 5.58-6.12-2.68-.16-5.35-.18-8.03-.21-.84-2.42-1.65-4.86-2.46-7.29l-2.3.36m26.34-.32c-.96 2.43-1.79 4.91-2.94 7.26-2.68-.08-5.37-.07-8.05-.06.06.53.17 1.61.23 2.14 1.8 1.37 3.63 2.68 5.37 4.12-.38 3.07-1.62 5.97-1.57 9.09 2.69-1.24 5.19-2.85 7.68-4.45 2.32 1.81 4.6 3.95 7.59 4.52-.46-3.02-1.36-5.97-1.37-9.05 2.08-1.69 5.88-2.86 5.41-6.16-2.67-.1-5.33-.12-8-.16-.84-2.34-1.59-4.72-2.34-7.09l-2.01-.16m25.96.01c-.95 2.42-1.83 4.88-2.92 7.24-2.68-.07-5.36-.07-8.04-.04.05.54.13 1.61.17 2.15 1.81 1.4 3.66 2.73 5.45 4.16-.52 3.03-1.81 5.93-1.55 9.07 2.64-1.35 5.12-2.97 7.65-4.5 2.32 1.8 4.56 4.1 7.64 4.42-.55-2.99-1.51-5.9-1.53-8.96 1.91-1.26 3.76-2.6 5.53-4.05-.04-.51-.13-1.54-.17-2.05-2.62-.15-5.24-.17-7.86-.18-.89-2.34-1.71-4.71-2.4-7.12-.5-.03-1.48-.11-1.97-.14m26.03-.26c-1.09 2.46-1.91 5.02-2.97 7.49-2.69-.05-5.37-.05-8.06-.03.05.54.16 1.61.21 2.15 1.74 1.44 3.58 2.76 5.37 4.14-.45 3.04-1.75 5.94-1.52 9.06 2.66-1.3 5.12-2.97 7.68-4.47 2.28 1.85 4.52 4.21 7.63 4.46-.44-2.81-1.34-5.51-2.32-8.17 2.11-2.29 6.38-3.25 6.37-6.9-2.7-.2-5.4-.2-8.1-.19-1.46-2.47-.9-6.83-4.29-7.54m25.61.42c-.74 2.4-1.64 4.75-2.61 7.07-2.96-.05-5.94-.14-8.89.17 1.41 2.73 4.02 4.45 6.46 6.16-.74 2.97-1.81 5.9-1.5 9.02 2.58-1.44 5.05-3.07 7.64-4.48 2.06 1.78 4.27 3.42 6.71 4.65.21-2.91-.26-5.78-1.43-8.45 2.03-2.31 6.46-3.25 6.37-6.84-2.71-.16-5.42-.19-8.13-.19-.99-2.32-1.81-4.7-2.39-7.16-.75.01-1.49.03-2.23.05z" />
...
CSS
.stars {
display: flex;
align-items: center;
margin-bottom: 24px;
max-width: 200px;
width: 100%;
}
.stars--disabled {
position: relative;
}
.stars--disabled:after {
position: absolute;
content: ' ';
background-color: transparent;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 2;
}
.stars__count {
font-size: 22px;
line-height: 1.2;
color: #4a4a4a;
padding-left: 12px;
margin-top: 4px;
font-weight: bold;
}
.stars__inner,
.stars__count {
position: relative;
z-index: 2;
}
.stars__progress {
position: absolute;
top: 0px;
left: 0px;
z-index: -1;
}
.stars__data {
cursor: pointer;
display: block;
}
.stars__data,
.stars__progress {
width: 130px;
height: 28px;
}
.stars svg {
width: 130px;
height: 28px;
}
JavaScript
//stars
function move(e, obj) {
var summ = 0;
var id = obj.next().attr('id').substr(1);
var progress = e.pageX - obj.offset().left;
var width = obj.width(),
leftEdge = obj.offset().left,
rightEdge = obj.offset().left + width;
if (e.pageX < leftEdge) {
progress = 0;
} else if (e.pageX >= rightEdge) {
progress = obj.width();
}
var rating = progress * 5 / width;
rating = Math.max(Math.ceil(rating), 1);
$('#param' + id).text(Math.ceil(rating).toFixed(1));
obj.next().width(progress);
$('.stars__count').each(function() {
summ += parseFloat($(this).text());
});
};
$('.stars__data').on('mouseleave', function(e) {
var summ = 0;
var id = $(this).next().attr('id').substr(1);
var width = $(this).width(),
reasonableWidth = width * 0.1,
height = $(this).height(),
leftEdge = $(this).offset().left,
topEdge = $(this).offset().top,
bottomEdge = topEdge + height,
exitPointX = e.pageX,
exitPointY = e.pageY;
if ((exitPointY >= topEdge) && (exitPointY <= bottomEdge) && (exitPointX > (leftEdge + reasonableWidth))) {
$('#param' + id).text("5.0");
$(this).next().width(width);
$('.stars__count').each(function() {
summ += parseFloat($(this).text());
});
}
});
$('.stars__data').click(function(e) {
move(e, $(this));
$(this).parents('.stars').addClass('stars--disabled');
console.log($('.stars__count').text());
});
$('.stars__data').on('mousemove', function(e) {
move(e, $(this));
});
$("#rating").on('mousemove', function(e) {
let width = $(this).width();
let left = $(this).offset().left;
let goPercentage = (e.clientX - left) / width * 100;
goPercentage = Math.max(Math.ceil(goPercentage / 20) * 20, 20);
let startPercentage = 100 - goPercentage;
function constrain(n, min, max) {
return Math.max(Math.min(n, max), min);
}
if (goPercentage...