Skip to content

Instantly share code, notes, and snippets.

@thinkphp
Created December 7, 2024 13:18
Show Gist options
  • Save thinkphp/7c0969d59e13b6769f47d429d06fbbb9 to your computer and use it in GitHub Desktop.
Save thinkphp/7c0969d59e13b6769f47d429d06fbbb9 to your computer and use it in GitHub Desktop.
rating
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
* {
box-sizing: border-box;
transition: all 0.3s ease;
}
body {
font-family: Arial, sans-serif;
margin: 0 auto;
max-width: 800px;
padding: 20px;
background-color: #f9f9f9;
}
.rating-card {
background: white;
border-radius: 12px;
padding: 30px;
box-shadow: 0 2px 15px rgba(0,0,0,0.1);
}
.heading {
font-size: 25px;
margin-bottom: 15px;
color: #333;
font-weight: bold;
display: block;
}
/* Stars styling remains the same */
.stars-container {
padding: 15px 0;
position: relative;
display: inline-block;
}
#stars {
display: inline-flex;
gap: 8px;
background: #f8f8f8;
padding: 10px 15px;
border-radius: 25px;
margin: 10px 0;
}
.fa-star {
font-size: 32px;
cursor: pointer;
color: #ddd;
transition: all 0.2s ease;
padding: 0 2px;
}
.fa-star:hover {
transform: scale(1.1);
}
.stars-container:hover .fa-star {
color: #ffd700;
}
.fa-star.checked {
color: #ffd700;
text-shadow: 0 0 5px rgba(255, 215, 0, 0.5);
}
.stars-container:hover .fa-star:hover ~ .fa-star {
color: #ddd;
}
/* Improved Graph Styling */
.ratings-graph {
margin-top: 30px;
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
}
.graph-row {
display: flex;
align-items: center;
margin: 12px 0;
padding: 5px 0;
}
.star-label {
width: 80px;
font-weight: 500;
color: #555;
display: flex;
align-items: center;
}
.star-label .fa-star {
font-size: 16px;
margin-left: 5px;
color: #ffd700;
}
.bar-container {
flex-grow: 1;
height: 25px;
background-color: #eef1f5;
border-radius: 12px;
margin: 0 15px;
overflow: hidden;
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
.bar {
height: 100%;
border-radius: 12px;
width: 0;
transition: width 1s cubic-bezier(0.4, 0, 0.2, 1);
}
.bar-5 {background: linear-gradient(90deg, #04AA6D, #06c17d);}
.bar-4 {background: linear-gradient(90deg, #2196F3, #21bbf3);}
.bar-3 {background: linear-gradient(90deg, #00bcd4, #00e5ff);}
.bar-2 {background: linear-gradient(90deg, #ff9800, #ffad33);}
.bar-1 {background: linear-gradient(90deg, #f44336, #ff6659);}
.count-label {
width: 60px;
text-align: right;
font-weight: 600;
color: #444;
font-size: 15px;
}
.percentage-label {
width: 60px;
text-align: right;
color: #666;
font-size: 13px;
margin-left: 10px;
}
/* Other styles remain the same */
.tooltip {
position: absolute;
background: #333;
color: white;
padding: 8px 15px;
border-radius: 20px;
font-size: 14px;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
top: -40px;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.user-rating {
margin-top: 20px;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
display: none;
border: 1px solid #eee;
}
/* Mobile Responsiveness */
@media (max-width: 600px) {
.rating-card {
padding: 15px;
}
.graph-row {
flex-wrap: wrap;
}
.star-label {
width: 60px;
font-size: 14px;
}
.bar-container {
margin: 0 10px;
}
.count-label, .percentage-label {
width: auto;
min-width: 50px;
font-size: 13px;
}
.percentage-label {
display: none;
}
}
</style>
</head>
<body>
<div class="rating-card">
<span class="heading">User Rating</span>
<div class="stars-container">
<div id="stars">
<span class="fa fa-star" data-value="1" title="Poor"></span>
<span class="fa fa-star" data-value="2" title="Fair"></span>
<span class="fa fa-star" data-value="3" title="Good"></span>
<span class="fa fa-star" data-value="4" title="Very Good"></span>
<span class="fa fa-star" data-value="5" title="Excellent"></span>
</div>
<div class="tooltip"></div>
</div>
<p id="average-rating">4.1 average based on 254 reviews.</p>
<div id="user-rating" class="user-rating">
<p>Your Rating: <span id="user-rating-value"></span></p>
<p class="rating-message"></p>
</div>
<div class="ratings-graph">
<div class="graph-row">
<div class="star-label">5 <span class="fa fa-star"></span></div>
<div class="bar-container"><div class="bar bar-5"></div></div>
<div class="count-label">150</div>
<div class="percentage-label">59%</div>
</div>
<div class="graph-row">
<div class="star-label">4 <span class="fa fa-star"></span></div>
<div class="bar-container"><div class="bar bar-4"></div></div>
<div class="count-label">63</div>
<div class="percentage-label">25%</div>
</div>
<div class="graph-row">
<div class="star-label">3 <span class="fa fa-star"></span></div>
<div class="bar-container"><div class="bar bar-3"></div></div>
<div class="count-label">15</div>
<div class="percentage-label">6%</div>
</div>
<div class="graph-row">
<div class="star-label">2 <span class="fa fa-star"></span></div>
<div class="bar-container"><div class="bar bar-2"></div></div>
<div class="count-label">6</div>
<div class="percentage-label">2%</div>
</div>
<div class="graph-row">
<div class="star-label">1 <span class="fa fa-star"></span></div>
<div class="bar-container"><div class="bar bar-1"></div></div>
<div class="count-label">20</div>
<div class="percentage-label">8%</div>
</div>
</div>
</div>
<script>
let totalReviews = 254;
let ratings = [150, 63, 15, 6, 20]; // Initial ratings count for 5-1 stars
let userRating = 0;
const stars = document.querySelectorAll("#stars .fa");
const averageRatingElement = document.getElementById("average-rating");
const userRatingDiv = document.getElementById("user-rating");
const tooltip = document.querySelector(".tooltip");
const ratingMessage = document.querySelector(".rating-message");
function calculateAverage() {
const totalScore = ratings.reduce((sum, count, index) => sum + count * (5 - index), 0);
return (totalScore / totalReviews).toFixed(1);
}
function updateBars() {
const bars = document.querySelectorAll(".bar");
const countLabels = document.querySelectorAll(".count-label");
const percentageLabels = document.querySelectorAll(".percentage-label");
ratings.forEach((count, index) => {
const percentage = (count / totalReviews) * 100;
requestAnimationFrame(() => {
bars[index].style.width = percentage + "%";
countLabels[index].textContent = count;
percentageLabels[index].textContent = `${percentage.toFixed(0)}%`;
});
});
}
function updateStars(rating) {
stars.forEach((star, index) => {
if (index < rating) {
star.classList.add("checked");
star.style.transform = "scale(1.1)";
} else {
star.classList.remove("checked");
star.style.transform = "scale(1)";
}
});
}
function showTooltip(event, rating) {
const titles = ["Poor", "Fair", "Good", "Very Good", "Excellent"];
tooltip.textContent = `Rate ${rating} star${rating > 1 ? 's' : ''} - ${titles[rating-1]}`;
tooltip.style.opacity = '1';
}
function hideTooltip() {
tooltip.style.opacity = '0';
}
function getRatingMessage(rating) {
const messages = {
1: "We're sorry to hear that. Please let us know how we can improve!",
2: "Thanks for the feedback. We'll work on getting better!",
3: "Thank you for your rating. We appreciate your feedback!",
4: "Thanks! We're glad you had a good experience!",
5: "Excellent! Thank you for your amazing feedback!"
};
return messages[rating];
}
stars.forEach(star => {
star.addEventListener("mouseover", (e) => {
const rating = parseInt(star.dataset.value);
showTooltip(e, rating);
stars.forEach((s, index) => {
if (index < rating) {
s.classList.add("checked");
s.style.transform = "scale(1.1)";
} else {
s.classList.remove("checked");
s.style.transform = "scale(1)";
}
});
});
star.addEventListener("mouseout", () => {
hideTooltip();
stars.forEach(s => s.style.transform = "scale(1)");
if (userRating > 0) {
updateStars(userRating);
} else {
updateStars(Math.round(calculateAverage()));
}
});
star.addEventListener("click", () => {
const rating = parseInt(star.dataset.value);
userRating = rating;
ratings[5 - rating]++;
totalReviews++;
const average = calculateAverage();
averageRatingElement.textContent = `${average} average based on ${totalReviews} reviews.`;
userRatingDiv.style.display = "block";
userRatingDiv.style.opacity = "0";
document.getElementById("user-rating-value").textContent = `${rating} star${rating > 1 ? 's' : ''}`;
ratingMessage.textContent = getRatingMessage(rating);
requestAnimationFrame(() => {
userRatingDiv.style.opacity = "1";
});
updateStars(rating);
updateBars();
});
});
// Initialize
updateBars();
updateStars(Math.round(calculateAverage()));
// Prevent selecting text when clicking stars
document.querySelector('.stars-container').addEventListener('mousedown', function(e) {
e.preventDefault();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment