【问题标题】:How to ensure that two setInterval last the same time如何确保两个 setInterval 持续相同的时间
【发布时间】:2018-02-25 05:14:14
【问题描述】:

我有一个带有 JS 动画的简单进度条。每 20 毫秒,进度条的值增加 0.25。因此完成进度条需要 20*4*100ms = 8 秒,如下面的 JSFiddle 所示。

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 秒,如下面的 JSFiddle 所示。

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>

我希望该函数始终具有相同的执行时间,而无需考虑起始值。 例如 0 到 -> 100 :4 秒,50 到 -> 100 也是 4 秒。

我试过了,但它不起作用:

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);

【问题讨论】:

    标签: javascript jquery html setinterval


    【解决方案1】:

    我想我会为此使用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>

    无论你选择使用requestAnimationFrame还是setInterval,我认为关键是让你的动画基于当前时间,而不是假设定时器会按时调用。

    当我运行您的原始代码时,它对我来说很好。我的猜测是问题是当间隔非常小时没有按计划调用计时器,这将取决于平台。 setInterval 在最好的情况下并不是非常准确,但对于从 0 到 100 的整个范围,您将依赖 10 毫秒的计时器,这个计时器小到足以产生问题。

    【讨论】:

    • 正是这样,当我想以 200 毫秒的持续时间从 0 到 100 时,就会出现问题,所以我的间隔是 200 / 100 / 4 = 0.5 毫秒。而且该栏完成的时间超过 200 毫秒,我找不到原因!非常感谢您的回答@skirtle
    猜你喜欢
    • 2016-12-19
    • 1970-01-01
    • 2021-12-04
    • 2021-03-23
    • 1970-01-01
    • 2023-01-20
    • 2014-02-10
    • 1970-01-01
    • 2013-12-22
    相关资源
    最近更新 更多