Countdown timer with a circular progress bar

I created a countdown timer. I got a border that was made circular. As the timer tends to zero, the circular border should change color with a decrease in seconds.

I created JSFIDDLE

HTML

<div class="outer"> <button class="btn btn-default btn-timer">0.00</button> </div> 

Js code

 var displayminutes; var displayseconds; var initializeTimer = 1.5 // enter in minutes var minutesToSeconds = initializeTimer*60; $("#document").ready(function(){ setTime = getTime(); $(".btn-timer").html(setTime[0]+":"+setTime[1]) }); $(".btn-timer").click(function(){ var startCountDownTimer = setInterval(function(){ minutesToSeconds = minutesToSeconds-1; var timer = getTime(); $(".btn-timer").html(timer[0]+":"+timer[1]); if(minutesToSeconds == 0){ clearInterval(startCountDownTimer); console.log("completed"); } },1000) }); function getTime(){ displayminutes = Math.floor(minutesToSeconds/60); displayseconds = minutesToSeconds - (displayminutes*60); if(displayseconds < 10) { displayseconds ="0"+displayseconds; } if(displayminutes < 10) { displayminutes = "0"+displayminutes; } return [displayminutes, displayseconds]; } 

How to get a circular progress bar. I was looking for some jQuery plugin, but they do not meet my requirement. I am looking for a way similar to this link

+3
source share
1 answer

The following is an example of a fragment of a countdown timer with a circular progress bar that changes color as the value decreases.

Basically, we do the following: (for more details, see the built-in comments in the code)

  • 4 additional div absolutely located on top of the parent. Each of them is a quadrant.
  • Initially, the tilt angle on all of them is 0 degrees, so they are all fully visible and cover the entire parent. This hides the box-shadow parent and thus makes it look like a solid circle.
  • At each iteration, we change the angle of inclination of each quadrant ( div ) so that the quadrants eventually become invisible one at a time and, thus, display the box-shadow parent.
  • Quadrants become invisible when the angle of inclination reaches +/- 90 degrees, and therefore at each iteration the angle is calculated as (90deg / no steps covered in this quadrant) .
  • As progress advances one quadrant to another, the parent's box-shadow changes so that when the progress bar appears, its color changes.
  • The source CodePen uses the value of the data-progress attribute directly as the content pseudo-element. But this value increases with each iteration. Since it is also used to calculate slope angles, I left it as it is and used a separate field for the countdown timer. The contents of the pseudo-elements cannot be set using JS, so I added another div for the timer text.

 window.onload = function() { var progressbar = document.querySelector('div[data-progress]'), quad1 = document.querySelector('.quad1'), quad2 = document.querySelector('.quad2'), quad3 = document.querySelector('.quad3'), quad4 = document.querySelector('.quad4'), counter = document.querySelector('.counter'); var progInc = setInterval(incrementProg, 1000); // call function every second function incrementProg() { progress = progressbar.getAttribute('data-progress'); //get current value progress++; // increment the progress bar value by 1 with every iteration progressbar.setAttribute('data-progress', progress); //set value to attribute counter.textContent = 100 - parseInt(progress, 10); // set countdown timer value setPie(progress); // call the paint progress bar function based on progress value if (progress == 100) { clearInterval(progInc); // clear timer when countdown is complete } } function setPie(progress) { /* If progress is less than 25, modify skew angle the first quadrant */ if (progress <= 25) { quad1.setAttribute('style', 'transform: skew(' + progress * (-90 / 25) + 'deg)'); } /* Between 25-50, hide 1st quadrant + modify skew angle of 2nd quadrant */ else if (progress > 25 && progress <= 50) { quad1.setAttribute('style', 'transform: skew(-90deg)'); // hides 1st completely quad2.setAttribute('style', 'transform: skewY(' + (progress - 25) * (90 / 25) + 'deg)'); progressbar.setAttribute('style', 'box-shadow: inset 0px 0px 0px 20px orange'); } /* Between 50-75, hide first 2 quadrants + modify skew angle of 3rd quadrant */ else if (progress > 50 && progress <= 75) { quad1.setAttribute('style', 'transform: skew(-90deg)'); // hides 1st completely quad2.setAttribute('style', 'transform: skewY(90deg)'); // hides 2nd completely quad3.setAttribute('style', 'transform: skew(' + (progress - 50) * (-90 / 25) + 'deg)'); progressbar.setAttribute('style', 'box-shadow: inset 0px 0px 0px 20px yellow'); } /* Similar to above for value between 75-100 */ else if (progress > 75 && progress <= 100) { quad1.setAttribute('style', 'transform: skew(-90deg)'); // hides 1st completely quad2.setAttribute('style', 'transform: skewY(90deg)'); // hides 2nd completely quad3.setAttribute('style', 'transform: skew(-90deg)'); // hides 3rd completely quad4.setAttribute('style', 'transform: skewY(' + (progress - 75) * (90 / 25) + 'deg)'); progressbar.setAttribute('style', 'box-shadow: inset 0px 0px 0px 20px green'); } } } 
 div[data-progress] { box-sizing: border-box; position: relative; height: 200px; width: 200px; background: beige; border-radius: 50%; box-shadow: inset 0px 0px 0px 20px red; transition: all 1s; overflow: hidden; } .counter { position: absolute; height: 100%; width: 100%; top: 0%; left: 0%; text-align: center; line-height: 200px; border-radius: 50%; background: transparent; z-index: 4; } div > div { position: absolute; height: 50%; width: 50%; background: inherit; border-radius: 0%; } .quad1, .quad2 { left: 50%; transform-origin: left bottom; } .quad3, .quad4 { left: 0%; transform-origin: right top; } .quad1, .quad4 { top: 0%; } .quad2, .quad3 { top: 50%; } .quad1, .quad3 { transform: skew(0deg); /* invisible at -90deg */ } .quad2, .quad4 { transform: skewY(0deg); /* invisible at 90deg */ } /* Just for demo */ body { background: linear-gradient(90deg, crimson, indianred, purple); } div[data-progress] { margin: 40px auto; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div data-progress="0"> <div class="quad1"></div> <div class="quad2"></div> <div class="quad3"></div> <div class="quad4"></div> <div class='counter'>100</div> </div> 

In the snippet below, I added a different background for each quadrant to provide a better visual illustration of what exactly is happening.

 window.onload = function() { var progressbar = document.querySelector('div[data-progress]'), quad1 = document.querySelector('.quad1'), quad2 = document.querySelector('.quad2'), quad3 = document.querySelector('.quad3'), quad4 = document.querySelector('.quad4'), counter = document.querySelector('.counter'); var progInc = setInterval(incrementProg, 1000); // call function every second function incrementProg() { progress = progressbar.getAttribute('data-progress'); //get current value progress++; // increment the progress bar value by 1 with every iteration progressbar.setAttribute('data-progress', progress); //set value to attribute counter.textContent = 100 - parseInt(progress, 10); // set countdown timer value setPie(progress); // call the paint progress bar function based on progress value if (progress == 100) { clearInterval(progInc); // clear timer when countdown is complete } } function setPie(progress) { /* If progress is less than 25, modify skew angle the first quadrant */ if (progress <= 25) { quad1.setAttribute('style', 'transform: skew(' + progress * (-90 / 25) + 'deg)'); } /* Between 25-50, hide 1st quadrant + modify skew angle of 2nd quadrant */ else if (progress > 25 && progress <= 50) { quad1.setAttribute('style', 'transform: skew(-90deg)'); // hides 1st completely quad2.setAttribute('style', 'transform: skewY(' + (progress - 25) * (90 / 25) + 'deg)'); progressbar.setAttribute('style', 'box-shadow: inset 0px 0px 0px 20px orange'); } /* Between 50-75, hide first 2 quadrants + modify skew angle of 3rd quadrant */ else if (progress > 50 && progress <= 75) { quad1.setAttribute('style', 'transform: skew(-90deg)'); // hides 1st completely quad2.setAttribute('style', 'transform: skewY(90deg)'); // hides 2nd completely quad3.setAttribute('style', 'transform: skew(' + (progress - 50) * (-90 / 25) + 'deg)'); progressbar.setAttribute('style', 'box-shadow: inset 0px 0px 0px 20px yellow'); } /* Similar to above for value between 75-100 */ else if (progress > 75 && progress <= 100) { quad1.setAttribute('style', 'transform: skew(-90deg)'); // hides 1st completely quad2.setAttribute('style', 'transform: skewY(90deg)'); // hides 2nd completely quad3.setAttribute('style', 'transform: skew(-90deg)'); // hides 3rd completely quad4.setAttribute('style', 'transform: skewY(' + (progress - 75) * (90 / 25) + 'deg)'); progressbar.setAttribute('style', 'box-shadow: inset 0px 0px 0px 20px green'); } } } 
 div[data-progress] { box-sizing: border-box; position: relative; height: 200px; width: 200px; background: beige; border-radius: 50%; box-shadow: inset 0px 0px 0px 20px red; transition: all 1s; overflow: hidden; } .counter { position: absolute; height: 100%; width: 100%; top: 0%; left: 0%; text-align: center; line-height: 200px; border-radius: 50%; background: transparent; z-index: 4; } div > div { position: absolute; height: 50%; width: 50%; border-radius: 0%; } .quad1, .quad2 { left: 50%; transform-origin: left bottom; } .quad3, .quad4 { left: 0%; transform-origin: right top; } .quad1, .quad4{ top: 0%; } .quad2, .quad3{ top: 50%; } .quad1, .quad3{ transform: skew(0deg); } .quad2, .quad4{ transform: skewY(0deg); } /* Just for demo */ body { background: linear-gradient(90deg, crimson, indianred, purple); } div[data-progress] { margin: 40px auto; } .quad1 { background: blue; } .quad2 { background: pink; } .quad3 { background: tan; } .quad4 { background: teal; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div data-progress="0"> <div class="quad1"></div> <div class="quad2"></div> <div class="quad3"></div> <div class="quad4"></div> <div class='counter'>100</div> </div> 
+9
source

All Articles