准确的 Javascript 计时器
Accurate Javascript Timer
我正在尝试构建一个准确的倒数计时器,以显示剩余的分钟数和秒数。我尝试了两种方法。方法 1 使用 setTimer 函数并计算漂移。对于这种方法,一些值被跳过,一些值被重复。方法 2 会产生所有必要的值,但这些值不会以均匀的间隔打印到屏幕上(在 repl.it 中测试)。我怎样才能制作一个既准确又能打印所有值的计时器?
方法一:
function countTime(duration) {
var expected = 1;
var secsLeft;
var startT = new Date().getTime();
var oneSecond = 1000;
var expected = startT + oneSecond;
window.setTimeout(step, oneSecond);
function step() {
var nowT = new Date().getTime();
var drift = nowT - expected;
if (drift > oneSecond) {
console.log("drift is over 1 second long!");
}
console.log('drift is ' + drift);
var msDelta = nowT - startT;
var secsLeft = duration - Math.floor(msDelta / 1000);
console.log("secsLeft" + secsLeft);
if (secsLeft === 0) {
++count;
console.log("cleared");
} else {
expected += oneSecond;
setTimeout(step, Math.max(0, oneSecond - drift));
}
}
}
countTime(60);
方法 2:
function countTime(duration) {
var expected = 1;
var secsLeft;
var inter;
var startT = new Date().getTime();
inter = setInterval(function() {
//change in seconds
var sChange = Math.floor((new Date().getTime() - startT) / 1000);
if (sChange === expected) {
expected++;
secsLeft = duration - sChange;
console.log("seconds Left" + secsLeft);
}
if (secsLeft === 0) {
window.clearInterval(inter);
console.log("cleared");
}
}, 100);
}
countTime(60);
function(){
date = get the date
curSeconds = compute the number of seconds to be displayed
if(oldSeconds!=curSeconds) then refresh display and do oldSeconds = curSeconds;
}
经常调用此函数,调用次数越多,您的计时器就会越准确。我建议你使用 requestAnimationFrame() 而不是 setTimout() 它将被调用每秒 60 次(周期 16ms)因为它是大多数显示器的刷新率,它是最大可见 "accuracy"。当页面不可见时也不会调用它。
简单、干净、长时间不漂移。
它也处理一段时间不被调用。
考虑使用 requestAnimationFrame
。
function countTime(duration) {
requestAnimationFrame(function(starttime) {
var last = null;
function frame(delta) {
var timeleft = Math.floor(duration - (delta - starttime)/1000),
minutes = Math.floor(timeleft/60),
seconds = timeleft%60;
if( timeleft > 0) {
if( last != timeleft) {
console.log("Time left: "+minutes+"m "+seconds+"s");
last = timeleft;
}
requestAnimationFrame(frame);
}
}
frame(starttime);
});
}
countTime(60);
这将精确到浏览器本身的帧率:)
我正在尝试构建一个准确的倒数计时器,以显示剩余的分钟数和秒数。我尝试了两种方法。方法 1 使用 setTimer 函数并计算漂移。对于这种方法,一些值被跳过,一些值被重复。方法 2 会产生所有必要的值,但这些值不会以均匀的间隔打印到屏幕上(在 repl.it 中测试)。我怎样才能制作一个既准确又能打印所有值的计时器?
方法一:
function countTime(duration) {
var expected = 1;
var secsLeft;
var startT = new Date().getTime();
var oneSecond = 1000;
var expected = startT + oneSecond;
window.setTimeout(step, oneSecond);
function step() {
var nowT = new Date().getTime();
var drift = nowT - expected;
if (drift > oneSecond) {
console.log("drift is over 1 second long!");
}
console.log('drift is ' + drift);
var msDelta = nowT - startT;
var secsLeft = duration - Math.floor(msDelta / 1000);
console.log("secsLeft" + secsLeft);
if (secsLeft === 0) {
++count;
console.log("cleared");
} else {
expected += oneSecond;
setTimeout(step, Math.max(0, oneSecond - drift));
}
}
}
countTime(60);
方法 2:
function countTime(duration) {
var expected = 1;
var secsLeft;
var inter;
var startT = new Date().getTime();
inter = setInterval(function() {
//change in seconds
var sChange = Math.floor((new Date().getTime() - startT) / 1000);
if (sChange === expected) {
expected++;
secsLeft = duration - sChange;
console.log("seconds Left" + secsLeft);
}
if (secsLeft === 0) {
window.clearInterval(inter);
console.log("cleared");
}
}, 100);
}
countTime(60);
function(){
date = get the date
curSeconds = compute the number of seconds to be displayed
if(oldSeconds!=curSeconds) then refresh display and do oldSeconds = curSeconds;
}
经常调用此函数,调用次数越多,您的计时器就会越准确。我建议你使用 requestAnimationFrame() 而不是 setTimout() 它将被调用每秒 60 次(周期 16ms)因为它是大多数显示器的刷新率,它是最大可见 "accuracy"。当页面不可见时也不会调用它。
简单、干净、长时间不漂移。
它也处理一段时间不被调用。
考虑使用 requestAnimationFrame
。
function countTime(duration) {
requestAnimationFrame(function(starttime) {
var last = null;
function frame(delta) {
var timeleft = Math.floor(duration - (delta - starttime)/1000),
minutes = Math.floor(timeleft/60),
seconds = timeleft%60;
if( timeleft > 0) {
if( last != timeleft) {
console.log("Time left: "+minutes+"m "+seconds+"s");
last = timeleft;
}
requestAnimationFrame(frame);
}
}
frame(starttime);
});
}
countTime(60);
这将精确到浏览器本身的帧率:)