Comment mettre en pause et reprendre la fonction setInterval () en utilisant Javascript?
Par exemple, j'ai peut-être un chronomètre pour vous dire le nombre de secondes pendant lesquelles vous avez consulté la page Web. Il y a un bouton "Pause" et "Reprendre". La raison pour laquelle clearInterval () ne fonctionnerait pas ici est que si l’utilisateur clique sur le bouton "Pause" à la 40ème seconde et la 800ème milliseconde, lorsqu’il clique sur le bouton "Reprendre", le nombre de secondes écoulées doit augmenter de 1 après 200 millisecondes. Si j'utilise la fonction clearInterval () sur la variable timer (lorsque le bouton de pause est cliqué), puis que j'utilise à nouveau la fonction setInterval () sur la variable timer (lorsque le bouton de reprise est cliqué), le nombre de secondes écoulées augmentera de 1 seulement après 1000 millisecondes, ce qui détruit la précision du chronomètre.
Alors, comment je fais ça?
Vous pouvez utiliser un drapeau pour suivre l’état:
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>
C’est ce que je ferais. Je ne sais pas si vous pouvez mettre en pause setInterval.
Remarque: ce système est simple et fonctionne plutôt bien pour les applications qui n'exigent pas un niveau de précision élevé, mais il ne tient pas compte du temps écoulé entre les ticks: si vous cliquez sur Pause après une demi-seconde et plus tard, cliquez sur Play Time sera éteint par une demi-seconde.
Vous ne devriez pas mesurer le temps en fonction d'intervalle. Économisez simplement du temps lorsque la minuterie a démarré et mesurez la différence lorsque la minuterie est arrêtée/en pause. Utilisez setInterval uniquement pour mettre à jour la valeur affichée. Il n’est donc pas nécessaire de suspendre la minuterie et vous obtiendrez ainsi la meilleure précision possible.
Alors que @Jonas Giuro a raison de dire ceci:
Vous ne pouvez pas mettre la fonction setInterval en pause, vous pouvez l’ARRÊTER (clearInterval) ou le laisser fonctionner.
D'autre part, ce comportement peut être simulé avec approche proposée par @VitaliyG :
Vous ne devriez pas mesurer le temps en fonction d'intervalle. Économisez simplement du temps lorsque la minuterie a démarré et mesurez la différence lorsque la minuterie est arrêtée/en pause. Utilisez setInterval uniquement pour mettre à jour la valeur affichée.
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>
Ajoutez simplement une classe qui indique à l’intervalle de ne rien faire. Par exemple: en vol stationnaire.
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"> </p>
<button id="pauseInterval">Pause</button></p>
Je recherche cette approche rapide et facile depuis des années. Je publie donc plusieurs versions pour la présenter au plus grand nombre.
Je sais que ce fil est vieux, mais cela pourrait être une autre solution:
var do_this = null;
function y(){
// what you wanna do
}
do_this = setInterval(y, 1000);
function y_start(){
do_this = setInterval(y, 1000);
};
function y_stop(){
do_this = clearInterval(do_this);
};
Le code suivant, fournit un moyen de précision pour suspendre la reprise d'une minuterie.
Comment ça marche:
Lorsque le temporisateur est repris après une pause, il génère un cycle de correction à l'aide d'une seule timeout
, qui prend en compte le décalage de pause (heure exacte à laquelle le temporisateur a été mis en pause entre les cycles). Une fois le cycle de correction terminé, il programme les cycles suivants avec une variable setInteval
régulière et poursuit normalement l'exécution du cycle.
Cela permet de suspendre/reprendre le chronomètre, sans perdre la synchronisation.
Code:
function Timer(_fn_callback_ , _timer_freq_){
let RESUME_CORRECTION_RATE = 2;
let _timer_statusCode_;
let _timer_clockRef_;
let _time_ellapsed_; // will store the total time ellapsed
let _time_pause_; // stores the time when timer is paused
let _time_lastCycle_; // stores the time of the last cycle
let _isCorrectionCycle_;
/**
* execute in each clock cycle
*/
const nextCycle = function(){
// calculate deltaTime
let _time_delta_ = new Date() - _time_lastCycle_;
_time_lastCycle_ = new Date();
_time_ellapsed_ += _time_delta_;
// if its a correction cicle (caused by a pause,
// destroy the temporary timeout and generate a definitive interval
if( _isCorrectionCycle_ ){
clearTimeout( _timer_clockRef_ );
clearInterval( _timer_clockRef_ );
_timer_clockRef_ = setInterval( nextCycle , _timer_freq_ );
_isCorrectionCycle_ = false;
}
// execute callback
_fn_callback_.apply( timer, [ timer ] );
};
// initialize timer
_time_ellapsed_ = 0;
_time_lastCycle_ = new Date();
_timer_statusCode_ = 1;
_timer_clockRef_ = setInterval( nextCycle , _timer_freq_ );
// timer public API
const timer = {
get statusCode(){ return _timer_statusCode_ },
get timestamp(){
let abstime;
if( _timer_statusCode_=== 1 ) abstime = _time_ellapsed_ + ( new Date() - _time_lastCycle_ );
else if( _timer_statusCode_=== 2 ) abstime = _time_ellapsed_ + ( _time_pause_ - _time_lastCycle_ );
return abstime || 0;
},
pause : function(){
if( _timer_statusCode_ !== 1 ) return this;
// stop timers
clearTimeout( _timer_clockRef_ );
clearInterval( _timer_clockRef_ );
// set new status and store current time, it will be used on
// resume to calculate how much time is left for next cycle
// to be triggered
_timer_statusCode_ = 2;
_time_pause_ = new Date();
return this;
},
resume: function(){
if( _timer_statusCode_ !== 2 ) return this;
_timer_statusCode_ = 1;
_isCorrectionCycle_ = true;
const delayEllapsedTime = _time_pause_ - _time_lastCycle_;
_time_lastCycle_ = new Date( new Date() - (_time_pause_ - _time_lastCycle_) );
_timer_clockRef_ = setTimeout( nextCycle , _timer_freq_ - delayEllapsedTime - RESUME_CORRECTION_RATE);
return this;
}
};
return timer;
};
let myTimer = Timer( x=> console.log(x.timestamp), 1000);
<input type="button" onclick="myTimer.pause()" value="pause">
<input type="button" onclick="myTimer.resume()" value="resume">
Code source:
This Timer est une version simplifiée et modifiée de advanced-timer
, une bibliothèque js créée par moi-même, avec beaucoup plus de fonctionnalités.
La bibliothèque complète et la documentation sont disponibles dans NPM et GITHUB