<div class="progress-demo">
<div class="progress-container">
<div class="progress-item">
<h3>Circular Progress</h3>
<div class="circular-progress" data-progress="75">
<svg class="circular-chart" viewBox="0 0 36 36">
<path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"/>
<path class="circle" stroke-dasharray="75, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"/>
<text x="18" y="20.35" class="percentage">75%</text>
</svg>
</div>
</div>
<div class="progress-item">
<h3>Linear Progress</h3>
<div class="linear-progress">
<div class="progress-bar">
<div class="progress-fill" data-progress="65"></div>
<span class="progress-label">65%</span>
</div>
</div>
</div>
<div class="progress-item">
<h3>Step Progress</h3>
<div class="step-progress">
<div class="step active" data-step="1">1</div>
<div class="step" data-step="2">2</div>
<div class="step" data-step="3">3</div>
<div class="step" data-step="4">4</div>
<div class="progress-line"></div>
</div>
</div>
<div class="progress-controls">
<button onclick="updateProgress('circular', 25)">25%</button>
<button onclick="updateProgress('circular', 50)">50%</button>
<button onclick="updateProgress('circular', 75)">75%</button>
<button onclick="updateProgress('circular', 100)">100%</button>
</div>
</div>
</div>
.progress-demo {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 20px;
}
.progress-container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 40px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
border: 1px solid rgba(255, 255, 255, 0.18);
max-width: 600px;
width: 100%;
}
.progress-item {
margin-bottom: 40px;
text-align: center;
}
.progress-item h3 {
color: white;
margin-bottom: 20px;
font-size: 1.2em;
font-weight: 600;
}
/* Circular Progress */
.circular-progress {
display: inline-block;
margin: 20px;
}
.circular-chart {
display: block;
margin: 10px auto;
max-width: 120px;
max-height: 120px;
}
.circle-bg {
fill: none;
stroke: rgba(255, 255, 255, 0.2);
stroke-width: 2.8;
}
.circle {
fill: none;
stroke-width: 2.8;
stroke-linecap: round;
animation: progress 1s ease-in-out forwards;
stroke: #4CAF50;
}
.percentage {
fill: white;
font-family: sans-serif;
font-size: 0.5em;
text-anchor: middle;
font-weight: bold;
}
/* Linear Progress */
.linear-progress {
margin: 20px 0;
}
.progress-bar {
position: relative;
width: 100%;
height: 20px;
background: rgba(255, 255, 255, 0.2);
border-radius: 10px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #4CAF50, #45a049);
border-radius: 10px;
transition: width 0.8s ease;
width: 65%;
position: relative;
}
.progress-label {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-weight: bold;
font-size: 0.9em;
}
/* Step Progress */
.step-progress {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
margin: 30px 0;
padding: 0 20px;
}
.step {
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
position: relative;
z-index: 2;
transition: all 0.3s ease;
}
.step.active {
background: #4CAF50;
transform: scale(1.1);
}
.progress-line {
position: absolute;
top: 50%;
left: 20px;
right: 20px;
height: 4px;
background: rgba(255, 255, 255, 0.2);
z-index: 1;
border-radius: 2px;
}
.progress-line::before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 33%;
background: #4CAF50;
border-radius: 2px;
transition: width 0.8s ease;
}
/* Controls */
.progress-controls {
display: flex;
gap: 10px;
justify-content: center;
flex-wrap: wrap;
margin-top: 30px;
}
.progress-controls button {
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 10px 20px;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
}
.progress-controls button:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
@keyframes progress {
0% {
stroke-dasharray: 0 100;
}
}
@media (max-width: 768px) {
.progress-container {
padding: 20px;
margin: 10px;
}
.progress-controls {
gap: 5px;
}
.progress-controls button {
padding: 8px 16px;
font-size: 0.9em;
}
}
class ProgressManager {
constructor() {
this.init();
}
init() {
this.animateCircular();
this.animateLinear();
this.animateSteps();
}
animateCircular(element = null) {
const circularProgress = element || document.querySelector('.circular-progress');
if (!circularProgress) return;
const progress = circularProgress.dataset.progress || 75;
const circle = circularProgress.querySelector('.circle');
const percentage = circularProgress.querySelector('.percentage');
if (circle && percentage) {
circle.style.strokeDasharray = `${progress}, 100`;
percentage.textContent = `${progress}%`;
}
}
animateLinear() {
const progressFill = document.querySelector('.progress-fill');
if (!progressFill) return;
const progress = progressFill.dataset.progress || 65;
progressFill.style.width = `${progress}%`;
const label = document.querySelector('.progress-label');
if (label) {
label.textContent = `${progress}%`;
}
}
animateSteps() {
const steps = document.querySelectorAll('.step');
const progressLine = document.querySelector('.progress-line');
if (!steps.length || !progressLine) return;
let activeStep = 1;
const totalSteps = steps.length;
steps.forEach((step, index) => {
step.classList.remove('active');
if (index < activeStep) {
step.classList.add('active');
}
});
const progressWidth = ((activeStep - 1) / (totalSteps - 1)) * 100;
const progressBar = progressLine.querySelector('::before') || progressLine;
if (progressBar.style) {
progressBar.style.setProperty('--progress-width', `${progressWidth}%`);
}
}
updateStepProgress(stepNumber) {
const steps = document.querySelectorAll('.step');
const progressLine = document.querySelector('.progress-line');
if (!steps.length || !progressLine) return;
steps.forEach((step, index) => {
step.classList.remove('active');
if (index < stepNumber) {
step.classList.add('active');
}
});
const progressWidth = ((stepNumber - 1) / (steps.length - 1)) * 100;
progressLine.style.setProperty('--progress-width', `${progressWidth}%`);
}
}
function updateProgress(type, value) {
switch(type) {
case 'circular':
const circular = document.querySelector('.circular-progress');
circular.dataset.progress = value;
new ProgressManager().animateCircular(circular);
break;
case 'linear':
const linear = document.querySelector('.progress-fill');
linear.dataset.progress = value;
linear.style.width = `${value}%`;
break;
}
}
document.addEventListener('DOMContentLoaded', function() {
new ProgressManager();
});