为什么在使用短间隔时更改CSS宽度会产生奇怪的效果?

时间:2018-10-01 14:06:50

标签: javascript jquery html css

这个想法是要有一个进度条,该进度条会在20秒内从0%加载到100%,然后从0开始。要实现这一点,我将setIntervaljQuery.css('width', '+=0.1%)结合使用。

一个间隔计数为20秒,另一个间隔每20毫秒将div的宽度增加0.1%。第一次计时器启动时应该达到100%,对吧?

但事实并非如此。首先,宽度未按预期添加:不是以0.1%的步长计算蜂鸣次数,而是在逗号后面放置更多位置。其次,这20秒在达到100%之前已经很长时间了。不同的浏览器在这里给出不同的结果。 Chrome在重新开始之前几乎接近100%,而在我的网站中达到70%时,Firefox已经过了20秒...

即使使用1%的步长而不是0.1%的步长,它仍然不能正确地相加,尽管应该没什么用,但我仍然在逗号后面找到了位置。

示例代码:

var interval;
$('.progressbar').css('width', '0%');
interval= setInterval(function() {
  $('.progressbar').css('width', '+=0.1%');
}, 20);

setInterval(startLoading, 20000);

function startLoading() {
  clearInterval(interval);
  $('.progressbar').css('width', '0%');
  interval= setInterval(function() {
    $('.progressbar').css('width', '+=0.1%');
  }, 20);
}
.progressbar{
    height: 10px;
    background: #0060ff;
    border-radius:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="progressbar"></div>

5 个答案:

答案 0 :(得分:3)

使用CSS动画或jquery .animate()

您只需将持续时间设置为20000,一切正常。如果您必须在某个时刻停止它,只需在动画回调中的progressBarLoop函数周围添加一个条件。 (我将持续时间设置为5000,因此我们不必等待20秒即可重新启动)

var stop = false;

function progressBarLoop() {
  $('.progressbar').css('width', '0%');
  $('.progressbar').animate({
    width:'100%'
  }, 5000, 'linear', function() {
    if(!stop) {
      progressBarLoop();
    }
  });
  
}

 progressBarLoop();
.progressbar{
    height: 10px;
    background: #0060ff;
    border-radius:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="progressbar"></div>

答案 1 :(得分:1)

  1. 保持时间的流逝,而不是设置计时器以提高准确性。
  2. 使用CSS3动画减少浏览器之间的计时器差异。

link可能有用

答案 2 :(得分:1)

为什么表现怪异?由于计时器不准确,您将现有宽度增加0.1%,而不是百分比增加0.1(0.1 + 0.1%= 0.1001%,等等)。

您的代码应看起来像这样……

$('.progressbar').css('width', '0%');

setTimeout(function startLoading() {
  var width = $('.progressbar').prop('style').width;
  var newWidth = parseFloat(width) + 0.1;

  if (newWidth < 100) {
    $('.progressbar').css('width', newWidth + '%');
  } else {
    $('.progressbar').css('width', '0%');
  }

  setTimeout(startLoading, 20);
}, 20);
.progressbar{
    height: 10px;
    background: #0060ff;
    border-radius:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="progressbar"></div>

答案 3 :(得分:1)

我不确定为什么要使用2个计时器来知道何时完成加载。 只需检查进度何时达到100并调用回调即可。

devtools::install_github('rstudio/bookdown')
function LoadingBar() {
    var self = this; // id use ES classes instead but you seem to prefer the old school way.
    this.element = $('.progressbar');
    this.progress = 0;
    this.stepSize = 0.1;
    this.progressInterval;
    this.start = function() {
         console.log('loading');
         self.progress = 0;
         if (self.progressInterval) {
             clearInterval(self.progressInterval);
         }
         
         self.progressInterval = setInterval(self.updateProgress, 10);
    }
    
    this.updateProgress = function() {
      self.progress += self.stepSize;
      // round off
      self.progress = Math.round(self.progress * 10) / 10;
      self.element.css('width', self.progress + '%');
      if (self.progress >= 100) {
        clearInterval(self.progressInterval);
        self.onComplete();
      }
    }
    this.onComplete = function() {
        console.log('completed');
        //start over
        self.start();
    }
}
var loadingBar = new LoadingBar();
loadingBar.start();
.progressbar{
  height: 10px;
  background: #0060ff;
  border-radius:20px;
}

https://jsfiddle.net/rainerpl/xpvt214o/858622/

答案 4 :(得分:1)

计时器不是非常准确。低于50毫秒的体验间隔可能会比预期的触发频率低100%(即每100毫秒),具体取决于许多因素。如果您希望进度填写20秒,那么计算每个刻度的实际百分比将使它看起来更准确。

var defaultDuration=20000; //Change this to whatever

function loadingBar(duration) {
    var interval;
    var startTime = new Date().getTime();
    var endTime = startTime + duration;

    $('.progressbar').css('width', '0%');
    interval= setInterval(function() { 
      var pc = (new Date().getTime() - startTime)/(endTime-startTime);
      $('.progressbar').css('width', (pc * 100) +'%');
    }, 20);
    return interval;
}
var int = loadingBar(defaultDuration); 
setInterval(function () { 
     clearInterval(int); 
     int = loadingBar(defaultDuration); 
}, defaultDuration);
.progressbar{
    height: 10px;
    background: #0060ff;
    border-radius:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="progressbar"></div>