如何在javascript中创建具有固定间隔的计时器?以及从数字开始的选项



我使用这个答案中的解决方案来创建一个准确的javascript计时器。代码运行良好。但我希望它有一个固定的间隔选项。比如它需要输出100200300等等..,

Math.round(timer.getTime() / 1000);此代码将值四舍五入到最接近的秒,因此计时器为1、2、3、4、5…

我试着将setInterval的持续时间调整为50,并四舍五入到最接近的100,它几乎可以满足我的需求。但它重复数字,有时跳过几个数字。

我还需要一些计时器来从一个特定的数字开始,比如从400到10000。该类默认为0。我该如何着手实施?

有关更多代码和详细信息,请找到代码笔:https://codepen.io/gurgoon32/pen/KKzYYKG

class Timer {
constructor() {
this.isRunning = false;
this.startTime = 0;
this.overallTime = 0;
}
_getTimeElapsedSinceLastStart() {
if (!this.startTime) {
return 0;
}
return Date.now() - this.startTime;
}
start() {
if (this.isRunning) {
return console.error('Timer is already running');
}
this.isRunning = true;
this.startTime = Date.now();
}
stop() {
if (!this.isRunning) {
return console.error('Timer is already stopped');
}
this.isRunning = false;
this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart();
}
reset() {
this.overallTime = 0;
if (this.isRunning) {
this.startTime = Date.now();
return;
}
this.startTime = 0;
}
getTime() {
if (!this.startTime) {
return 0;
}
if (this.isRunning) {
return this.overallTime + this._getTimeElapsedSinceLastStart();
}
return this.overallTime;
}
}
let the_interval;
function round_nearest_hundred(num) {
return Math.round(num / 100) * 100;
}
function onUpdateTimer(duration) {
const timeInSeconds = Math.round(timer.getTime() / 1000);
document.getElementById('time').innerText = timeInSeconds;
document.getElementById('accTime').innerText = round_nearest_hundred(timer.getTime());
console.log(round_nearest_hundred(timer.getTime()));
if (round_nearest_hundred(timer.getTime()) >= duration) {
document.getElementById('status').innerText = 'complete';
timer.stop();
timer_manager(false);
}
}
function timer_manager(flag, updateFunction, time, duration) {
if (flag) {
the_interval = setInterval(function() {
updateFunction(duration);
}, time);
} else {
clearInterval(the_interval);
}
}

const timer = new Timer();
//timer.start();
timer_manager(true, onUpdateTimer, 50, 10000);
document.getElementById('start').addEventListener('click', function() {
timer.start();
});
document.getElementById('stop').addEventListener('click', function() {
timer.stop();
});
document.getElementById('restart').addEventListener('click', function() {
timer_manager(true, onUpdateTimer, 100, 10000);
timer.reset();
timer.start();
});
<p>Elapsed time: <span id="time">0</span>s</p>
<p id="accTime"></p>
<p id="status"></p>
<button id="start">start</button>
<button id="stop">pause</button>
<button id="restart">restart</button>

尝试一下:

class Timer {
constructor () {
this.isRunning = false;
this.startTime = 0;
this.overallTime = 0;
}
_getTimeElapsedSinceLastStart () {
if (!this.startTime) {
return 0;
}

return Date.now() - this.startTime;
}
start () {
if (this.isRunning) {
return console.error('Timer is already running');
}
this.isRunning = true;
this.startTime = Date.now();
}
stop () {
if (!this.isRunning) {
return console.error('Timer is already stopped');
}
this.isRunning = false;
this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart();
}
reset () {
this.overallTime = 0;
if (this.isRunning) {
this.startTime = Date.now();
return;
}
this.startTime = 0;
}
getTime () {
if (!this.startTime) {
return 0;
}
if (this.isRunning) {
return this.overallTime + this._getTimeElapsedSinceLastStart();
}
return this.overallTime;
}
}
let the_interval;
function round_nearest_hundred(num){
return Math.floor(num / 100)*100;
}
function onUpdateTimer(start, duration){
const startTime = timer.getTime() + start;
const timeInSeconds = Math.floor(timer.getTime() / 1000);
document.getElementById('time').innerText = timeInSeconds;

document.getElementById('accTime').innerText = round_nearest_hundred(startTime);

console.log(round_nearest_hundred(startTime));

if(round_nearest_hundred(timer.getTime()) >= (duration - start)){
document.getElementById('status').innerText = 'complete';
timer.stop();
timer_manager(false);
}
}
function timer_manager(flag, updateFunction, time, start, duration){
if(flag){
the_interval =  setInterval(function(){updateFunction(start, duration);}, time);
} else {
clearInterval(the_interval);
}   
}

const timer = new Timer();
//timer.start();
timer_manager(true, onUpdateTimer, 50, 1000, 10000);
document.getElementById('start').addEventListener('click', function(){
timer.start();
});
document.getElementById('stop').addEventListener('click', function(){
timer.stop();
});
document.getElementById('restart').addEventListener('click', function(){
timer_manager(false);
timer_manager(true, onUpdateTimer, 100, 0, 10000);
timer.reset();
timer.start();
});
<p>Elapsed time: <span id="time">0</span>s</p>
<p id="accTime"></p>
<p id="status"></p>
<button id="start">start</button>
<button id="stop">pause</button>
<button id="restart">restart</button>

  1. Math.round()在这种情况下有点令人困惑,因为它意味着500毫秒四舍五入到1,让你认为你在真正到达之前就已经到达了那个时间。最好使用Math.floor()(四舍五入(,这样您只能看到实际经过的秒数。我认为这应该解决跳过的问题。

  2. Reset函数中,最好在设置新间隔之前清除最后一个间隔。否则,您将运行两个setInterval函数,变量the_interval只引用最近的一个函数。

  3. 为了从一个特定的数字开始,我在timer_manager函数中添加了一个参数(start(。这会传递给onUpdateTimer函数,因为这是您的逻辑决定计时器是否完成的地方(很明显,这将取决于它从哪个值开始(。最后,在该功能中,您也可以决定是否向用户显示实际经过的秒数(例如,开始:1s,结束:10s,经过:9s(,或者加上起点(例如,结束:1s,经过:10s(。

为了提供开始时间值,您只需修改构造函数,使其接受开始时间作为参数:

class Timer {
constructor (startTime = 0) {
this.isRunning = false;
this.startTime = startTime;
this.overallTime = startTime;
}
// ...   
}
const timer1 = new Timer(); // timer1 will start from 0
const timer2 = new Timer(500); // timer2 will start from 500

关于间隔,如果你想显示四舍五入到一百的百分之一秒(例如100、200、300…(,你必须将间隔时间设置为10ms,并使用函数";round_nearest_hundred(("你已经有了:

// ...
function onUpdateTimer(duration) {
//const timeInSeconds = Math.round(timer.getTime() / 1000);
//document.getElementById('time').innerText = timeInSeconds;
const timeInHundredthsOfSeconds = round_nearest_hundred(timer.getTime());
document.getElementById('time').innerText = HundredthsOf;
document.getElementById('accTime').innerText = round_nearest_hundred(timer.getTime());
console.log(round_nearest_hundred(timer.getTime()));
if (round_nearest_hundred(timer.getTime()) >= duration) {
document.getElementById('status').innerText = 'complete';
timer.stop();
timer_manager(false);
}
}
// ...
timer_manager(true, onUpdateTimer, 10, 10000);
// ...

最新更新