Javascript - Приостановка setInterval()

Как приостановить и возобновить функцию setInterval() с помощью Javascript?

Например, возможно, у меня есть секундомер, чтобы рассказать вам количество секунд, которые вы просматривали на веб-странице. Появляются кнопки "Пауза" и "Возобновить". Причина, по которой clearInterval() не будет работать здесь, заключается в том, что если пользователь нажимает кнопку "Пауза" на 40-й и 800-й миллисекундах, когда он нажимает кнопку "Возобновить", количество прошедших секунд должно увеличиваться на 1 после 200 миллисекунд. Если я использую функцию clearInterval() в переменной таймера (при нажатии кнопки паузы), а затем снова используя функцию setInterval() в переменной таймера (когда нажата кнопка возобновления), количество прошедших секунд будет увеличиваться на 1 только после 1000 миллисекунд, что разрушает точность секундомера.

Итак, как мне это сделать?

Ответ 1

Вы можете использовать флаг для отслеживания состояния:

var output = $('h1');
var isPaused = false;
var time = 0;
var t = window.setInterval(function() {
  if(!isPaused) {
    time++;
    output.text("Seconds: " + time);
  }
}, 1000);

//with jquery
$('.pause').on('click', function(e) {
  e.preventDefault();
  isPaused = true;
});

$('.play').on('click', function(e) {
  e.preventDefault();
  isPaused = false;
});
h1 {
    font-family: Helvetica, Verdana, sans-serif;
    font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Seconds: 0</h1>
<button class="play">Play</button>
<button class="pause">Pause</button>

Ответ 2

Вы не должны измерять время в функции интервала. Вместо этого просто сэкономьте время, когда таймер был запущен, и измерьте разницу, когда таймер был остановлен/приостановлен. Используйте setInterval только для обновления отображаемого значения. Таким образом, нет необходимости останавливать таймер, и таким образом вы получите максимально возможную точность.

Ответ 3

Почему бы не использовать более простой подход? Добавьте класс!

Просто добавьте класс, который сообщает интервалу ничего не делать. Например: при наведении.

var i = 0;
this.setInterval(function() {
  if(!$('#counter').hasClass('pauseInterval')) { //only run if it hasn't got this class 'pauseInterval'
    console.log('Counting...');
    $('#counter').html(i++); //just for explaining and showing
  } else {
    console.log('Stopped counting');
  }
}, 500);

/* In this example, I'm adding a class on mouseover and remove it again on mouseleave. You can of course do pretty much whatever you like */
$('#counter').hover(function() { //mouse enter
    $(this).addClass('pauseInterval');
  },function() { //mouse leave
    $(this).removeClass('pauseInterval');
  }
);

/* Other example */
$('#pauseInterval').click(function() {
  $('#counter').toggleClass('pauseInterval');
});
body {
  background-color: #eee;
  font-family: Calibri, Arial, sans-serif;
}
#counter {
  width: 50%;
  background: #ddd;
  border: 2px solid #009afd;
  border-radius: 5px;
  padding: 5px;
  text-align: center;
  transition: .3s;
  margin: 0 auto;
}
#counter.pauseInterval {
  border-color: red;  
}
<!-- you'll need jQuery for this. If you really want a vanilla version, ask -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<p id="counter">&nbsp;</p>
<button id="pauseInterval">Pause</button></p>

Ответ 4

Хотя @Jonas Giuro прав, говоря, что:

Вы не можете использовать PAUSE для функции setInterval, вы можете остановить ее (clearInterval) или запустить ее

С другой стороны, это поведение можно моделировать с помощью подхода @VitaliyG:

Вы не должны измерять время в функции интервала. Вместо этого просто сэкономьте время, когда таймер был запущен, и измерьте разницу, когда таймер был остановлен/приостановлен. Используйте setInterval только для обновления отображаемого значения.

var output = $('h1');
var isPaused = false;
var time = new Date();
var offset = 0;
var t = window.setInterval(function() {
  if(!isPaused) {
    var milisec = offset + (new Date()).getTime() - time.getTime();
    output.text(parseInt(milisec / 1000) + "s " + (milisec % 1000));
  }
}, 10);

//with jquery
$('.toggle').on('click', function(e) {
  e.preventDefault();
  isPaused = !isPaused;
  if (isPaused) {
    offset += (new Date()).getTime() - time.getTime();
  } else {
    time = new Date();
  }

});
h1 {
    font-family: Helvetica, Verdana, sans-serif;
    font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Seconds: 0</h1>
<button class="toggle">Toggle</button>