Created
December 7, 2024 13:18
-
-
Save thinkphp/7c0969d59e13b6769f47d429d06fbbb9 to your computer and use it in GitHub Desktop.
rating
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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