基于CSS和JS实现带动画的半圆形技能进度条
Got it, let's turn that linear progress bar into a smooth animated semicircular one! This solution checks all your boxes:
- Pure CSS + vanilla JS (no frameworks)
- Animated progress arc and counting percentage on page load
- Configurable target percentage directly in HTML
- Fully responsive
Step 1: Updated HTML Structure
We'll use a container with a data-percent attribute to set our target value. Inside, we have the background semicircle, progress arc, and percentage text—super easy to tweak without touching CSS/JS:
<div class="semicircle-progress" data-percent="75"> <div class="progress-background"></div> <div class="progress-arc"></div> <div class="percent-text"> <span id="count">0</span>% </div> </div> <div class="text-label">Total Score</div>
Step 2: CSS for Semicircle & Animation
We'll create the semicircle effect by clipping circular elements, then animate the progress arc's rotation. The --size variable lets you adjust the overall dimensions while keeping everything responsive:
:root { --size: 150px; /* Adjust this to resize the semicircle */ --progress-color: #1565C0; --bg-color: #eee; } .semicircle-progress { position: relative; width: var(--size); height: calc(var(--size) / 2); margin: 20px auto; } /* Background semicircle base */ .progress-background, .progress-arc { position: absolute; width: 100%; height: 200%; border-radius: 50%; border: 12px solid var(--bg-color); box-sizing: border-box; clip: rect(0, var(--size), calc(var(--size) / 2), 0); /* Clip bottom half to make semicircle */ } /* Animated progress arc */ .progress-arc { border-color: var(--progress-color); transform: rotate(-180deg); /* Start at the left end of the semicircle */ transition: transform 2s ease-in-out; } /* Centered percentage text */ .percent-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 1.5em; font-weight: bold; } .text-label { font-size: 14px; text-align: center; margin-top: 10px; } /* Responsive shrink for small screens */ @media (max-width: 480px) { :root { --size: 120px; } }
Step 3: Vanilla JS for Syncing Animation & Counting
We'll modify your existing counting logic to also update the progress arc's rotation. The key trick here is converting progress percentage to a rotation angle—since a semicircle is 180 degrees, 1% = 1.8 degrees:
document.addEventListener('DOMContentLoaded', () => { const progressContainer = document.querySelector('.semicircle-progress'); const countEl = document.getElementById('count'); const progressArc = document.querySelector('.progress-arc'); // Pull target percentage directly from HTML data attribute const finalPercent = parseInt(progressContainer.dataset.percent, 10); const duration = 2000; // Animation length in milliseconds let start; const animateProgress = (timestamp) => { if (!start) start = timestamp; const elapsed = timestamp - start; const progress = Math.min(elapsed / duration, 1); // Cap progress at 100% // Update the counting text const currentCount = Math.floor(progress * finalPercent); countEl.textContent = currentCount; // Rotate the progress arc: starts at -180deg (left) → ends at 0deg (right) const rotationAngle = -180 + (progress * 180); progressArc.style.transform = `rotate(${rotationAngle}deg)`; if (progress < 1) { requestAnimationFrame(animateProgress); } }; // Kick off the animation when the page loads requestAnimationFrame(animateProgress); });
Quick Breakdown
- Semicircle Shape: We use
clip: rect()to cut the bottom half of circular elements, turning them into semicircles. - Progress Animation: The blue arc starts rotated fully left (-180deg) and animates to the right (0deg) as progress hits 100%.
- Easy Configuration: Just change the
data-percentvalue in the HTML to set a new target percentage. - Responsiveness: The
--sizeCSS variable and media queries ensure the semicircle scales smoothly on phones, tablets, and desktops.
内容的提问来源于stack exchange,提问作者TinyTiger

