我有一个主秒表,每个步骤有4个迷你秒表。完成一段时间后,这里有一个定时器应该如何显示的例子:
MAIN: 00 : 14 : 57
-------------------
MINI1: 00 : 04 . 17
MINI2: 00 : 06 . 40
MINI3: 00 : 02 . 54
MINI4: 00 : 01 . 46
迷你定时器应该加到主计时器上,就像在这种情况下一样。使用我当前的计时器,它似乎总是.02
毫秒关闭,因此在这种情况下它们将加起来00 : 14 . 55
而不是00 : 14 . 57
。
这是我当前定时器的JSFiddle。我认为问题最有可能发生在stopwatch.js
文件中,但我不确定为什么会出现这种情况,因为我使用Date.now()
来计算已经过了多长时间。这是stopwatch.js
文件,它是单个秒表的代码:
class Stopwatch {
constructor (opts) {
this.isOn = false;
this.time = 0;
this.elem = opts.elem;
}
start () {
this.offset = Date.now();
this.interval = setInterval(() => this._update(), 10);
this.isOn = true;
}
stop () {
clearInterval(this.interval);
this.offset = null;
this.interval = null;
this.isOn = false;
}
reset () {
this.time = 0;
this._render();
}
_update () {
this.time += this._getTimePassed();
this._render();
}
_getTimePassed () {
const now = Date.now();
const timePassed = now - this.offset;
this.offset = now;
return timePassed;
}
_timeFormatter (milliseconds) {
const padZero = (time) => `0${time}`.slice(-2);
const minutes = padZero(milliseconds / 60000 | 0);
const seconds = padZero((milliseconds / 1000 | 0) % 60);
const centiseconds = padZero((milliseconds / 10 | 0) % 100);
return `${minutes} : ${seconds} . ${centiseconds}`;
}
_render () {
this.elem.textContent = this._timeFormatter(this.time);
}
}
我在上面提到的JSFiddle中以及在gist中完全包含了所有内容,如果它更容易阅读的话。任何指导都将不胜感激。
答案 0 :(得分:5)
你在谈论20毫秒的延迟,这可能是由很多事情造成的。
Date.now()
setInterval
漂移!在这里a bin to prove it。您无法真正期望在单个线程上运行的语言能够以每10毫秒完美准确地安排任务,并且您的_update
方法只需要这样做。为了正确解决这个问题,我建议您重新设计您的解决方案,以便将所有秒表包裹在StopwatchManager
中,这会立即渲染所有秒表,并通过添加来计算主表的总时间迷你的时代。您可能还希望使用requestAnimationFrame
代替setInterval
进行渲染。
答案 1 :(得分:1)
你正在停止一个计时器,在下一行中,开始下一个计时器。你的问题部分是时间在这两个方法调用之间传递。
此外,您的“停止”方法甚至不使用当前时间,它只是从上次更新后追溯停止,它不会进行最终_update
。
如果您真的想要精确添加,请在Date.now()
方法中取updateMiniTimers
,并将其传递给两个调用,以确保它们在同一时间点停止/启动,并执行此操作stop
来电后的最终渲染。
一般来说,在方法中:
method() {
var a = Date.now();
var b = Date.now();
}
a和b绝对不能保证是相同的,没有方法调用是瞬时的。
答案 2 :(得分:1)
我同意法拉兹关于可能的原因。我还会检查各个部门的舍入错误。无论如何,如果你想让它更健壮和可扩展,你可以将你的时间点视为List中不断扩展的元素。每当秒表开始时,您将列表中最后一个元素的索引记录为起始点,每当结束时,您将最后一个元素的索引记录为终点。这将允许您具有准确的计时器层次结构。