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

如何确保两个setInterval持续相同的时间

  •  0
  • Vald  · 技术社区  · 9 年前

    function updateProgress(currentValue, expectedValue){
        var inProgress = setInterval(function() {
          currentValue = currentValue + 0.25;
          $('#progress-bar').attr('value', currentValue);
          $('#progress-text').text(Math.round(currentValue));
          if (currentValue == expectedValue) clearInterval(inProgress);
        }, 20);
      }
    
    
    updateProgress(0, 100);
    <progress id="progress-bar" value="0" max="100"></progress>
    <div><span id="progress-text">0</span>%</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

    因此,如果我使用相同的代码,并以50%而不是0%的速度启动进度条,则需要20*4*50ms=4秒才能完成进度条,正如您在下面的JSFIDLE中看到的那样。

    function updateProgress(currentValue, expectedValue){
        var inProgress = setInterval(function() {
          currentValue = currentValue + 0.25;
          $('#progress-bar').attr('value', currentValue);
          $('#progress-text').text(Math.round(currentValue));
          if (currentValue == expectedValue) clearInterval(inProgress);
        }, 20);
      }
    
    
    updateProgress(50, 100);
    <progress id="progress-bar" value="50" max="100"></progress>
    <div><span id="progress-text">50</span>%</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

    我希望函数始终具有相同的执行时间,与起始值无关。

    我试过这个,但不起作用:

    function updateProgress(currentValue, expectedValue){
      var interval = 4000 / (expectedValue - currentValue) / 4;
    
      var inProgress = setInterval(function() {
          currentValue = currentValue + 0.25;
          $('#progress-bar').attr('value', currentValue);
          $('#progress-text').text(Math.round(currentValue));
          if (currentValue == expectedValue) clearInterval(inProgress);
      }, interval);
    }
    
    updateProgress(50, 100);
    
    1 回复  |  直到 9 年前
        1
  •  1
  •   skirtle    9 年前

    我想我会用 requestAnimationFrame 为此,这就是它的设计目的。

    function updateProgress(currentValue, expectedValue){
      var valueDelta = expectedValue - currentValue,
          startTime = performance.now();
          
      nextFrame(startTime);
      
      function nextFrame(time) {
          var value = Math.min(expectedValue, currentValue + valueDelta * (time - startTime) / 4000);
          
          setValue(value);
          
          if (value !== expectedValue) {
              requestAnimationFrame(nextFrame);
          }
      }
      
      function setValue(value) {
          $('#progress-bar').attr('value', value);
          $('#progress-text').text(Math.round(value));
      }
    }
    
    updateProgress(50, 100);
    <progress id="progress-bar" value="50" max="100"></progress>
    <div><span id="progress-text">50</span>%</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

    是否选择使用 setInterval ,我认为关键是根据当前时间制作动画,而不是假设计时器会按计划调用。

    当我运行你的原始代码时,它对我来说很好。我的猜测是,问题是当间隔很小时,计时器没有按计划调用,这将取决于平台。 即使在最好的情况下也不是超精确的,但对于0到100的全范围,您将依赖10ms计时器,该计时器足够小,可能会出现问题。