代码之家  ›  专栏  ›  技术社区  ›  Danmoreng

为什么在使用短间隔时更改CSS宽度的行为会很奇怪?

  •  3
  • Danmoreng  · 技术社区  · 7 年前

    这个想法是要有一个进度条,它在20秒内从0%加载到100%,然后从0开始重新加载。为了完成我用 setInterval 结合 jQuery.css('width', '+=0.1%) .

    但事实并非如此。首先,宽度没有按预期添加:它不是按0.1%的步长计算的,而是在逗号后面加了更多的位置。第二,20秒在达到100%之前已经过去了。不同的浏览器在这里给出不同的结果。Chrome在重新开始之前已经接近100%,Firefox在我的网站上达到70%的时候20秒已经过去了。。。

    示例代码:

    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 回复  |  直到 7 年前
        1
  •  3
  •   Alexis Vandepitte    7 年前

    .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>
        2
  •  1
  •   Coffee'd Up Hacker    7 年前

    你的代码应该更像这样。。。

    $('.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
  •   Rainer Plumer    7 年前

    我不知道为什么你用两个计时器来知道什么时候加载完成。 只要检查进度达到100并调用回调。

    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;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    
    <div class="progressbar"></div>

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

        4
  •  1
  •   Electron    7 年前
    1. 使用CSS3动画来减少浏览器之间的计时器差异。

    link 可能有用

        5
  •  1
  •   apokryfos    7 年前

    计时器不是超精确的。从经验来看,低于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>