<div>
<div id="progress-1" class="progress" progress="75">
<div class="progress-bar-outline"></div>
<div class="progress-bar"></div>
<div class="progress-label">
<span>△</span>
<h3 class="progress-label-count"></h3>
<span style="font-size: .5rem;">Please Wait, on progress..</span>
</div>
</div>
<br><br>
<div id="progress-2" class="progress" progress="50">
<div class="progress-bar-outline"></div>
<div class="progress-bar"></div>
<div class="progress-label">
<span>△</span>
<h3 class="progress-label-count"></h3>
<span style="font-size: .5rem;">Please Wait, on progress..</span>
</div>
</div>
<br><br>
<div id="progress-3" class="progress" progress="100">
<div class="progress-bar-outline"></div>
<div class="progress-bar"></div>
<div class="progress-label">
<span>△</span>
<h3 class="progress-label-count"></h3>
<span style="font-size: .5rem;">Please Wait, on progress..</span>
</div>
</div>
<br><br>
</div>
* {
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: Arial, Helvetica, sans-serif;
color: white;
height: 100vh;
background-color: hsl(218, 17%, 9%);
background-color: #afb8c8;
}
.progress {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.progress-bar {
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
filter: blur(3px);
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
.progress-bar-outline {
position: absolute;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
background-color: #ffffff8a;
backdrop-filter: blur(5px);
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
.progress-label {
position: absolute;
background-color: #333;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
.progress-label-count {
letter-spacing: .1rem;
}
.progress-bar.end {
animation: progressEnd 1s linear;
}
@keyframes progressEnd {
0% { filter: blur(3px) contrast(1); }
50% { filter: blur(0px) contrast(1.5); }
100% { filter: blur(3px) contrast(1); }
}
class Progress {
constructor(element, options = {}) {
this.element = element;
this._progress = 0;
this.targetProgress = options.progress || parseInt(element.getAttribute('progress'), 10) || 0;
this.duration = options.duration || 1000;
this.color = options.color || '#4caf50';
this.shadow = options.shadow || '#4caf50';
this.size = options.size || "200px";
this.animationFrameId = null;
this.lineSize = (100 - options.lineSize) || 95;
this.lineBackground = options.lineBackground || '#dddddda9';
this.updateProgressBar();
this.animateProgress();
}
get progress() {
return this._progress;
}
set progress(value) {
this.targetProgress = value;
this.animateProgress();
}
updateProgressBar() {
const progressBar = this.element.querySelector('.progress-bar');
const progressLabel = this.element.querySelector('.progress-label');
const progressLabelCount = this.element.querySelector('.progress-label-count');
this.element.style.width = this.size;
this.element.style.height = this.size;
this.element.style.filter = `drop-shadow(0 10px 20px ${this.shadow})`;
progressBar.style.setProperty('--progress', `${this._progress}%`);
progressBar.style.background = `conic-gradient(${this.color} var(--progress), transparent var(--progress))`;
progressLabelCount.textContent = `${Math.round(this._progress)}%`;
progressLabelCount.style.textShadow = `0 20px 40px ${this.shadow}`;
progressLabel.style.width = this.lineSize + '%';
progressLabel.style.height = this.lineSize + '%';
}
animateProgress() {
this._progress = 0;
this.updateProgressBar();
if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId);
const startTime = performance.now();
const animate = () => {
const currentTime = performance.now();
const elapsed = currentTime - startTime;
const progressRatio = Math.min(elapsed / this.duration, 1);
this._progress = this.targetProgress * progressRatio;
this.updateProgressBar();
if (progressRatio < 1) {
this.animationFrameId = requestAnimationFrame(animate);
}else {
console.log('done');
this.onEndEffect();
}
};
this.animationFrameId = requestAnimationFrame(animate);
}
onEndEffect() {
const progressBar = this.element.querySelector('.progress-bar');
progressBar.classList.add('end');
}
}
const config = {
progress: 0,
duration: 5000,
color: '#4caf50',
shadow: '#4caf50',
size: '180px',
lineSize: 95,
lineBackground: '#dddddda9',
onEndEffect: () => {
console.log('done');
}
};
new Progress(document.querySelector('#progress-1'), {
duration: 5000,
color: '#4caf68',
shadow: '#4caf8c',
size: '180px',
});
new Progress(document.querySelector('#progress-2'), {
duration: 5000,
color: '#6553BD',
shadow: '#B26BD1',
size: '180px',
});
new Progress(document.querySelector('#progress-3'), {
duration: 4000,
color: '#B64155',
shadow: '#D2675D',
size: '180px',
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.