问题
I created an countdown timer. I got a border which is made circular. As the timer is tending towards zero, the circular border should change color with decrement in the seconds.
I created the 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 do I a get a circular progress bar. I looked for some jQuery plugin but they are not matching my requirement. I am looking for an output similar to this link
回答1:
Below is a sample snippet for the countdown timer with a circular progress bar that changes color as the value comes down.
Basically what we are doing is the follows: (refer inline comments in code for more details)
- 4 additional
div
are absolutely positioned on top of the parent. Each represents a quadrant. - Initially the skew angle on all of them is 0 degree, so they are all fully visible and cover the entire parent. This hides the
box-shadow
of the parent and thus makes it look like a solid circle. - At every iteration, we modify the skew angle of each quadrant (
div
) such that the quadrants eventually become invisible one by one and thus revealing thebox-shadow
of parent. - The quadrants become invisible when the skew angle reaches +/- 90 degrees and so at each iteration the angle is calculated as (90deg / no. of steps covered in that quadrant).
- As the progress moves past one quadrant to another, the
box-shadow
of the parent is changed to give the appearance of the progress bar changing its color. - The original CodePen uses the
data-progress
attribute's value directly as thecontent
of a pseudo-element. But that value gets incremented with every iteration. Since it is also used in calculation of the skew angles, I have left it as-is and used a separate field for the countdown timer. Content of pseudo-elements cannot be set using JS and so I have added anotherdiv
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's 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 below snippet, I have 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's 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>
来源:https://stackoverflow.com/questions/31198304/count-down-timer-with-circular-progress-bar