使用循环进度条倒计时器

时间:2015-07-03 04:09:10

标签: javascript jquery css css3 css-shapes

我创建了一个倒数计时器。我有一个圆形的边框。当计时器趋于零时,圆形边框应该以秒为单位递减颜色。

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];
}

如何获得循环进度条。我找了一些jQuery插件,但它们不符合我的要求。我正在寻找类似to this link

的输出

1 个答案:

答案 0 :(得分:9)

下面是倒数计时器的示例片段,其中包含一个圆形进度条,当值降低时会改变颜色。

基本上我们正在做的是:(在代码中引用内联注释以获取更多详细信息)

  • 另外4个div绝对位于父级之上。每个代表一个象限。
  • 最初所有这些的倾斜角度都是0度,所以它们都是完全可见的并覆盖整个父级。这会隐藏父级的box-shadow,从而使其看起来像一个实心的圆圈。
  • 在每次迭代中,我们修改每个象限(div)的倾斜角度,使象限最终逐个变为隐形,从而揭示父级的box-shadow
  • 当倾斜角度达到+/- 90度时,象限变得不可见,因此在每次迭代时角度计算为(该象限覆盖的90度/步数)。
  • 当进度超过一个象限时,父级的box-shadow会更改,以使进度条的外观更改其颜色。
  • 原始CodePen直接使用data-progress属性的值作为伪元素的content。但是每次迭代都会增加该值。因为它也用于计算倾斜角度,所以我保持原样,并为倒数计时器使用单独的字段。无法使用JS设置伪元素的内容,因此我为计时器文本添加了另一个div

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>

在下面的代码段中,我为每个象限添加了一个不同的background,以便更准确地直观地了解到底发生了什么。

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>