动态启动和停止多个间隔循环

时间:2018-04-23 00:54:08

标签: javascript jquery

对于页面上的多个进度圈,我需要等量的计时器来更新其进度百分比数和颜色。它们都从0开始,一直到data-current-progress值。

选择颜色

我有一组特定的100种颜色,从红色到橙色,最后是绿色,在阵列中;

var ProgressColourTween = [
    "#ff4400", "#ff4900", "#ff4a00", "#ff4c00", "#ff4d00",
       ...        ...        ...        ...        ...
    "#8cc400", "#8ac500", "#87c600", "#85c700", "#82c800"
];

每种颜色都是一个百分比的实体表示,因此在1%时它会看起来相当红,大约50%橙色和100%绿色。

更新进度数值

在循环中,从0到data-current-progress值,例如i++,我将更新值。

  <div class="numbers">
      <span>0%</span>
  </div>

问题

如果这是我正在进行的单个进度循环,通过简单地命名一个计时器然后在以后结束它会更容易,但是通过使用几个,我发现很难启动几个并停止当它们完成时而不是在另一个完成时它们。

如何为预期目的动态创建,启动然后停止多个间隔循环?

演示:http://jsfiddle.net/7urppm3s/

1 个答案:

答案 0 :(得分:3)

为每个.circle设置计时器,并计算每个计时器执行的百分比。

var ProgressColourTween = [
  "#ff4400", "#ff4900", "#ff4a00", "#ff4c00", "#ff4d00", "#ff4f00", "#ff5000", "#ff5100", "#ff5200", "#ff5400",
  "#ff5600", "#ff5700", "#ff5900", "#ff5a00", "#ff5c00", "#ff5c00", "#ff5e00", "#ff5f00", "#ff6100", "#ff6300",
  "#ff6400", "#ff6600", "#ff6700", "#ff6800", "#ff6900", "#ff6b00", "#ff6c00", "#ff6e00", "#ff6f00", "#ff7100",
  "#ff7200", "#ff7300", "#ff7500", "#ff7600", "#ff7800", "#ff7900", "#ff7a00", "#ff7c00", "#ff7d00", "#ff7f00",
  "#ff8700", "#ff8800", "#ff8a00", "#ff8b00", "#ff8c00", "#ff8e00", "#ff8f00", "#ff9100", "#ff9200", "#ff9400",
  "#ff9400", "#fc9500", "#fa9600", "#f79700", "#f59800", "#f29900", "#f09a00", "#ed9c00", "#eb9c00", "#e89e00",
  "#e69e00", "#e3a000", "#e0a100", "#dea200", "#dba300", "#d9a400", "#d6a500", "#d4a600", "#d1a700", "#cfa800",
  "#cca900", "#c9ab00", "#c7ab00", "#c4ad00", "#c2ae00", "#bfaf00", "#bdb000", "#bab100", "#b8b200", "#b5b300",
  "#b3b400", "#b0b500", "#adb600", "#abb700", "#a8b900", "#a6b900", "#a3bb00", "#a1bb00", "#9ebd00", "#9cbe00",
  "#99bf00", "#96c000", "#94c100", "#91c200", "#8fc300", "#8cc400", "#8ac500", "#87c600", "#85c700", "#82c800"
];

var transitionTime = 2; // second

!(function($) {

  "use strict";

  $(function() {
    $('.radial-progress').TCHQProgCirc();
  });

  $.fn.TCHQProgCirc = function() {

    return this.each(function() {
      var $this = $(this)
      $this.find(".circle .mask, .circle .fill").css({
        'transition': "transform " + transitionTime + "s"
      });

      var rotateTo = $this.data("current-progress");

      $this.css({
        '--pf': (rotateTo * 1.8) + "deg",
        '--pff': (rotateTo * 3.6) + "deg",
        '--pfwid': (rotateTo * 57) + "px"
      })

      colorTween($this);

    });
  };
})(jQuery);

function colorTween($this) {
  $this.timer = setInterval(function() {
    $this.step = $this.step || 1;
    var c = $this.step++;
    var totalPercentage = $this.data("current-progress");
    var colorIndex = Math.floor(c * totalPercentage/100)
    var color = ProgressColourTween[colorIndex];

    $this.find('.fill').css('background-color', color)

    var percentage = Math.floor(totalPercentage * c / 100); // current percentage

    $this.find('.numbers span').text(`${percentage}%`)

    c++;

    if (c > 100) {
      clearTimeout($this.timer)
    }
  }, transitionTime * 1000 / 100);
}
.clear {
  clear: both;
}

.radial-progress {
  float: left;
  margin: 50px;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  --pf: 0deg;
  --pff: 0deg;
  --pfwid: 0;
}

.radial-progress .circle .mask,
.radial-progress .circle .fill,
.radial-progress .circle .shadow {
  width: 120px;
  height: 120px;
  position: absolute;
  border-radius: 50%;
}

.radial-progress .circle .shadow {
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.2) inset;
}

.radial-progress .circle .mask,
.radial-progress .circle .fill {
  -webkit-backface-visibility: hidden;
  transition: transform 1s;
  border-radius: 50%;
}

.radial-progress .circle .mask {
  clip: rect(0px, 120px, 120px, 60px);
}

.radial-progress .circle .mask .fill {
  clip: rect(0px, 60px, 120px, 0px);
  background-color: #97a71d;
}

@keyframes move-in-steps {
  0% {
    background: red;
  }
  50% {
    background: yellow;
  }
  100% {
    background: #97a71d;
  }
}

.radial-progress.coloring .circle .mask .fill {
  animation: move-in-steps 1s;
}

.radial-progress .inset {
  width: 90px;
  height: 90px;
  position: absolute;
  margin-left: 15px;
  margin-top: 15px;
  background-color: #fbfbfb;
  border-radius: 50%;
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.2);
}

.radial-progress .inset .percentage {
  height: 22px;
  width: 57px;
  overflow: hidden;
  position: absolute;
  top: 34px;
  left: 16.5px;
  line-height: 1;
}

.radial-progress .inset .percentage .numbers span {
  width: 57px;
  display: inline-block;
  vertical-align: top;
  text-align: center;
  font-weight: 800;
  font-size: 22px;
  /*font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;*/
  color: #97a71d;
}

.radial-progress .circle .mask.full,
.radial-progress .circle .fill {
  transform: rotate( var(--pf));
}

.radial-progress .circle .fill.fix {
  transform: rotate( var(--pff));
}

.radial-progress .inset .percentage .numbers {
  width: var(--pfwid);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="radial-progress" data-current-progress="25">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

<div class="radial-progress" data-current-progress="50">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<div class="radial-progress" data-current-progress="75">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

<div class="radial-progress" data-current-progress="100">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

编辑:根据评论,我添加了一个可以暂停和恢复的新版本。代码的详细说明在代码注释中。

var ProgressColourTween = [
  "#ff4400", "#ff4900", "#ff4a00", "#ff4c00", "#ff4d00", "#ff4f00", "#ff5000", "#ff5100", "#ff5200", "#ff5400",
  "#ff5600", "#ff5700", "#ff5900", "#ff5a00", "#ff5c00", "#ff5c00", "#ff5e00", "#ff5f00", "#ff6100", "#ff6300",
  "#ff6400", "#ff6600", "#ff6700", "#ff6800", "#ff6900", "#ff6b00", "#ff6c00", "#ff6e00", "#ff6f00", "#ff7100",
  "#ff7200", "#ff7300", "#ff7500", "#ff7600", "#ff7800", "#ff7900", "#ff7a00", "#ff7c00", "#ff7d00", "#ff7f00",
  "#ff8700", "#ff8800", "#ff8a00", "#ff8b00", "#ff8c00", "#ff8e00", "#ff8f00", "#ff9100", "#ff9200", "#ff9400",
  "#ff9400", "#fc9500", "#fa9600", "#f79700", "#f59800", "#f29900", "#f09a00", "#ed9c00", "#eb9c00", "#e89e00",
  "#e69e00", "#e3a000", "#e0a100", "#dea200", "#dba300", "#d9a400", "#d6a500", "#d4a600", "#d1a700", "#cfa800",
  "#cca900", "#c9ab00", "#c7ab00", "#c4ad00", "#c2ae00", "#bfaf00", "#bdb000", "#bab100", "#b8b200", "#b5b300",
  "#b3b400", "#b0b500", "#adb600", "#abb700", "#a8b900", "#a6b900", "#a3bb00", "#a1bb00", "#9ebd00", "#9cbe00",
  "#99bf00", "#96c000", "#94c100", "#91c200", "#8fc300", "#8cc400", "#8ac500", "#87c600", "#85c700", "#82c800"
];

var transitionTime = 2; // second

!(function($) {

  "use strict";

  $(function() {
    $('.radial-progress').TCHQProgCirc();
  });

  $.fn.TCHQProgCirc = function() {

    return this.each(function() {
      var $this = $(this)

      // set trasitionTime
      $this.find(".circle .mask, .circle .fill").css({
        'transition': "transform " + transitionTime / 20 + "s"
      });

      colorTween($this);

    });
  };
})(jQuery);

var timerFlag = true;

function colorTween($this) {
  $this.timer = setInterval(function() {
    if (!timerFlag) {
      // if click "Pause" button, stop the function
      return;
    }

    // set the number of this function execute times, if $this.step is undefined at first, set it to 1
    $this.step = $this.step || 1;

    // assing c equals to $this.step, and makes $this.step = $this.step + 1 after assignment
    var c = $this.step++;

    // get the total percentage of this circle would be
    var totalPercentage = $this.data("current-progress");

    // calculate the current percentage
    // e.g. if the totalPercentage is 25%, in the first loop of the setInterval, 
    // percentage would be (25 * 1 / 100) = 0.25
    // then get the largest integer less than or equal to 0.25 which is 0

    // if the totalPercentage is 25%, in the end of the setInterval loop, 
    // percentage would be (25 * 100 / 100) = 25
    // then get the largest integer less than or equal to 25 which is 25

    // This makes us to select the right color
    var percentage = Math.floor(totalPercentage * c / 100);
    var color = ProgressColourTween[percentage];

    // calculate the variables to right values, you should know these better than I do since this is from your code ;)
    var pf = (1.8 * percentage)
    var pff = (3.6 * percentage)

    $this.css({
      '--pf': pf + "deg",
      '--pff': pff + "deg",
    })

    // change the color of fill bar
    $this.find('.fill').css('background-color', color)

    // change the percentage
    $this.find('.numbers span').text(`${percentage}%`)

    if (c >= 100) {
      // if current step is 100, clear timers
      clearTimeout($this.timer)
    }
  }, transitionTime * 1000 / 100); // convert transitionTime to milisecond and divide it into 100
}

$('button').on('click', function() {
  var paused = $(this).text() == "Pause"
  if (paused) {
    // if click "Pause" button, set flag to false, makes the timer stop from increasing the percentage
    timerFlag = false
  } else {
    // if click "Continue" button, set flag to true
    timerFlag = true
  }
  $(this).text(paused ? "Continue" : "Pause")
})
.clear {
  clear: both;
}

.radial-progress {
  float: left;
  margin: 50px;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  --pf: 0deg;
  --pff: 0deg;
  --pfwid: 0;
}

.radial-progress .circle .mask,
.radial-progress .circle .fill,
.radial-progress .circle .shadow {
  width: 120px;
  height: 120px;
  position: absolute;
  border-radius: 50%;
}

.radial-progress .circle .shadow {
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.2) inset;
}

.radial-progress .circle .mask,
.radial-progress .circle .fill {
  -webkit-backface-visibility: hidden;
  transition: transform 1s;
  border-radius: 50%;
}

.radial-progress .circle .mask {
  clip: rect(0px, 120px, 120px, 60px);
}

.radial-progress .circle .mask .fill {
  clip: rect(0px, 60px, 120px, 0px);
  background-color: #97a71d;
}

@keyframes move-in-steps {
  0% {
    background: red;
  }
  50% {
    background: yellow;
  }
  100% {
    background: #97a71d;
  }
}

.radial-progress.coloring .circle .mask .fill {
  animation: move-in-steps 1s;
}

.radial-progress .inset {
  width: 90px;
  height: 90px;
  position: absolute;
  margin-left: 15px;
  margin-top: 15px;
  background-color: #fbfbfb;
  border-radius: 50%;
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.2);
}

.radial-progress .inset .percentage {
  height: 22px;
  width: 57px;
  overflow: hidden;
  position: absolute;
  top: 34px;
  left: 16.5px;
  line-height: 1;
}

.radial-progress .inset .percentage .numbers span {
  width: 57px;
  display: inline-block;
  vertical-align: top;
  text-align: center;
  font-weight: 800;
  font-size: 22px;
  /*font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;*/
  color: #97a71d;
}

.radial-progress .circle .mask.full,
.radial-progress .circle .fill {
  transform: rotate( var(--pf));
}

.radial-progress .circle .fill.fix {
  transform: rotate( var(--pff));
}

.radial-progress .inset .percentage .numbers {
  width: var(--pfwid);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Pause</button>
<div class="radial-progress" data-current-progress="25">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

<div class="radial-progress" data-current-progress="50">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<div class="radial-progress" data-current-progress="75">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>

<div class="radial-progress" data-current-progress="100">
  <div class="circle">
    <div class="mask full">
      <div class="fill"></div>
    </div>
    <div class="mask half">
      <div class="fill"></div>
      <div class="fill fix"></div>
    </div>
    <div class="shadow"></div>
  </div>
  <div class="inset">
    <div class="percentage">
      <div class="numbers">
        <span>0%</span>
      </div>
    </div>
  </div>
</div>