<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',
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.