了解 setInterval 中的剩余时间并将其应用于暂停和恢复计时器

Knowing time left in a setInterval and applying it to pausing and resuming of a timer

这个问题一直在我脑海中盘旋,今天我有了解决这个问题的想法,但没有奏效。我基本上想要的是能够暂停和恢复计时器,当我恢复它时,它应该在我离开它的时候继续,例如:我在它所在的那一秒中间停止它,所以当我恢复它,半秒后进入下一秒。这是我的代码。

$(document).ready(function() {
  a = new Timer("#timerText");
  a.set(12, 1);
  a.run();
});

function Timer(element) {

  var minutes, seconds, finalTimeInSeconds, displayMinutes, displaySeconds, interval = 1000, self = this, timeLeftToNextSecond = 1000;

  this.set = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds = inputMinutes * 60 + inputSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.add = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds += inputMinutes * 60 + inputSeconds;
    finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.subtract = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds -= inputMinutes * 60 + inputSeconds;
    finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.reset = function() {

    this.set(0, 0);
  }

  this.print = function() {

    displayMinutes = (minutes.toString().length == 1) ? "0" + minutes : minutes; //ternary operator: adds a zero to the beggining 
    displaySeconds = (seconds.toString().length == 1) ? "0" + seconds : seconds; //of the number if it has only one caracter.

    $(element).text(displayMinutes + ":" + displaySeconds);
  }

  this.run = function() {

    ac = setInterval(function() {

      secondStarted = new Date;
      self.subtract(0, 1);
      interval = 1000;
    }, interval);
  }

  this.stop = function() {

    stopped = new Date;
    interval = stopped - secondStarted;
    clearInterval(ac);

  }

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="timerText">00:00</div>

没用。如果我停止它然后恢复它,interval 不会在一个周期后返回到 1000。另外,我认为我减去 Dates 的方式不正确,因为当我打印 interval 数字时,数字看起来有点偏差。我在这里做错了什么?

谢谢你的回答。

主要问题是 setInterval 函数被调用一次,然后如果您更改 interval 变量的值,这不会影响 setInterval 调用。

一个快速补丁可能是使用 setTimeout 代替:递归调用。

  this.run = function() {
    var _f = function() {
      secondStarted = new Date;
      self.subtract(0, 1);
      interval = 1000;
      ac = setTimeout(_f,interval);
    }
    ac = setTimeout(_f, interval);
  }

当然还有 stop 函数

clearTimeout(ac);

还有一个问题。 interval 变量不是 stopped-secondStarted 而是:

interval = 1000-(stopped - secondStarted);

这就是用您的方法解决您的具体问题的方法。 另请参阅 ac var 是全局的,不在范围内。

如果你想要一个更准确的计时器,你需要改变方法,因为 these function are inaccurate

$(document).ready(function() {
  a = new Timer("#timerText");
  a.set(12, 1);
  a.run();
   $('#btn').click(function() {
        if(a.running) {
            a.stop();
        }else {
            a.run();
        }
   });
});


function Timer(element) {

  var minutes, seconds, finalTimeInSeconds, displayMinutes, displaySeconds, interval = 1000, self = this, timeLeftToNextSecond = 1000;
  this.running = false;
  this.set = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds = inputMinutes * 60 + inputSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.add = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds += inputMinutes * 60 + inputSeconds;
    finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.subtract = function(inputMinutes, inputSeconds) {

    finalTimeInSeconds -= inputMinutes * 60 + inputSeconds;
    finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
    minutes = (Math.floor(finalTimeInSeconds / 60));
    seconds = finalTimeInSeconds % 60;

    this.print();
  }

  this.reset = function() {

    this.set(0, 0);
  }

  this.print = function() {

    displayMinutes = (minutes.toString().length == 1) ? "0" + minutes : minutes; //ternary operator: adds a zero to the beggining 
    displaySeconds = (seconds.toString().length == 1) ? "0" + seconds : seconds; //of the number if it has only one caracter.

    $(element).text(displayMinutes + ":" + displaySeconds);
  }

  this.run = function() {
    this.running = !false;
    var _f = function() {
      secondStarted = new Date;
      self.subtract(0, 1);
      interval = 1000;
      ac = setTimeout(_f,interval);
    }
    ac = setTimeout(_f, interval);
  }
  this.stop = function() {
    this.running = false;
    stopped = new Date;
    interval = 1000 -(stopped - secondStarted);
    clearTimeout(ac);

  }

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="timerText">00:00</div>
<button type="button" id="btn">Toggle Start</button>