chr*_*ong 47 javascript setinterval
如何使用Javascript暂停和恢复setInterval()函数?
例如,也许我有一个秒表来告诉你你在网页上看到的秒数.有一个"暂停"和"恢复"按钮.clearInterval()在这里不起作用的原因是因为如果用户在第40秒和第800毫秒点击"暂停"按钮,当他点击"恢复"按钮时,经过的秒数必须增加1 200毫秒.如果我在timer变量上使用clearInterval()函数(单击暂停按钮时),然后再次对timer变量使用setInterval()函数(单击恢复按钮时),经过的秒数将增加1仅在1000毫秒后,这会破坏秒表的准确性.
那我该怎么做?
Jon*_*ann 92
您可以使用标志来跟踪状态:
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;
});Run Code Online (Sandbox Code Playgroud)
h1 {
font-family: Helvetica, Verdana, sans-serif;
font-size: 12px;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
这正是我要做的,我不确定你是否可以实际暂停setInterval.
注意:这个系统很简单,对于不需要高精度的应用程序非常有效,但它不会考虑时间间隔之间的时间:如果你在半秒后点击暂停,然后点击播放你的时间将休息半秒钟.
Vit*_*iyG 11
您不应该在间隔函数中测量时间.而只是节省计时器启动时的时间,并在计时器停止/暂停时测量差异.仅使用setInterval更新显示的值.因此,无需暂停计时器,您将以这种方式获得最佳准确性.
ome*_*mer 10
我写了一个简单的 ES6 类,可能会派上用场。受到/sf/answers/4100664291/答案的启发
export class IntervalTimer {
callbackStartTime;
remaining = 0;
paused = false;
timerId = null;
_callback;
_delay;
constructor(callback, delay) {
this._callback = callback;
this._delay = delay;
}
pause() {
if (!this.paused) {
this.clear();
this.remaining = new Date().getTime() - this.callbackStartTime;
this.paused = true;
}
}
resume() {
if (this.paused) {
if (this.remaining) {
setTimeout(() => {
this.run();
this.paused = false;
this.start();
}, this.remaining);
} else {
this.paused = false;
this.start();
}
}
}
clear() {
clearInterval(this.timerId);
}
start() {
this.clear();
this.timerId = setInterval(() => {
this.run();
}, this._delay);
}
run() {
this.callbackStartTime = new Date().getTime();
this._callback();
}
}
Run Code Online (Sandbox Code Playgroud)
用法非常简单,
const interval = new IntervalTimer(console.log('aaa'), 3000);
interval.start();
interval.pause();
interval.resume();
interval.clear();
Run Code Online (Sandbox Code Playgroud)
虽然@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();
}
});Run Code Online (Sandbox Code Playgroud)
h1 {
font-family: Helvetica, Verdana, sans-serif;
font-size: 12px;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
只需添加一个告诉间隔什么都不做的类。例如:悬停。
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');
});Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
<!-- 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>Run Code Online (Sandbox Code Playgroud)
我一直在寻找这种快速,简便的方法,因此,我发布了多个版本,以尽可能多地向人们介绍该方法。
我的简单方法:
function Timer (callback, delay) {
let callbackStartTime
let remaining = 0
this.timerId = null
this.paused = false
this.pause = () => {
this.clear()
remaining -= Date.now() - callbackStartTime
this.paused = true
}
this.resume = () => {
window.setTimeout(this.setTimeout.bind(this), remaining)
this.paused = false
}
this.setTimeout = () => {
this.clear()
this.timerId = window.setInterval(() => {
callbackStartTime = Date.now()
callback()
}, delay)
}
this.clear = () => {
window.clearInterval(this.timerId)
}
this.setTimeout()
}
Run Code Online (Sandbox Code Playgroud)
如何使用:
let seconds = 0
const timer = new Timer(() => {
seconds++
console.log('seconds', seconds)
if (seconds === 8) {
timer.clear()
alert('Game over!')
}
}, 1000)
timer.pause()
console.log('isPaused: ', timer.paused)
setTimeout(() => {
timer.resume()
console.log('isPaused: ', timer.paused)
}, 2500)
function Timer (callback, delay) {
let callbackStartTime
let remaining = 0
this.timerId = null
this.paused = false
this.pause = () => {
this.clear()
remaining -= Date.now() - callbackStartTime
this.paused = true
}
this.resume = () => {
window.setTimeout(this.setTimeout.bind(this), remaining)
this.paused = false
}
this.setTimeout = () => {
this.clear()
this.timerId = window.setInterval(() => {
callbackStartTime = Date.now()
callback()
}, delay)
}
this.clear = () => {
window.clearInterval(this.timerId)
}
this.setTimeout()
}Run Code Online (Sandbox Code Playgroud)
代码写得很快,没有重构,如果你想让我改进代码并给出ES2015版本(类),请提高我的答案的评级。