javascript - 如何修复此 Javascript 秒表时钟中的停止启动过程?
问题描述
我在这里有一个 JavaScript 秒表,我需要开始-停止按钮在继续时保持相同的时间。目前,如果我停止并继续时钟差异是荒谬的,例如 '-19330839:-3:-53'
谁能解释这是如何解决的?
我制作了各种方法秒表;但是我宁愿使用实际日期时间而不是计数器,这是因为(我在意识到这一点后进行了测试)计数器在一段时间内非常不准确。
任何帮助深表感谢。
html:
请暂时忽略重置按钮。我稍后会配置它。
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();"/>
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
JS:
const outputElement = document.getElementById("outputt");
var startTime = 0;
var running = false;
var splitcounter = 0;
function startstop() {
if (running == false) {
running = true;
startTime = new Date(sessionStorage.getItem("time"))
if (isNaN(startTime)) startTime = Date.now();
startstopbutton.value = 'Stop';
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
updateTimer();
} else {
running = false;
logTime();
startstopbutton.value = 'Start';
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
function updateTimer() {
if (running == true) {
let differenceInMillis = Date.now() - startTime;
sessionStorage.setItem("time", differenceInMillis)
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
requestAnimationFrame(updateTimer);
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
我只需要计时器从它停止的地方继续。
解决方案
您的代码存在问题:
- 您从 sessionStorage 的初始值开始,
Date.now
然后在更新时保存差异。 - 您与会话存储进行了很多交互。与外部 API 的任何通信都是昂贵的。而是使用局部变量并找到一个事件来初始化值。
- 时差逻辑有点不对劲。
Date.now - startTime
不考虑停止动作和开始动作之间的区别。- 您可以使用此逻辑:如果定义了 startTime,则计算差异并将其添加到开始时间。如果不是,将其初始化为
Date.now()
建议:
- 不要添加样式,而是使用类。这将帮助您重置功能
- 定义小特征,并在此基础上定义小功能。这将使可重用性变得容易
- 尝试通过传递参数使函数独立,并且只依赖它们。这样你会减少副作用
注意:由于 SO 不允许访问 Session Storage,我已经删除了所有相关代码。
const outputElement = document.getElementById("outputt");
var running = false;
var splitcounter = 0;
var lastTime = 0;
var startTime = 0;
function logTime() {
console.log('Time: ', lastTime)
}
function resetclock() {
running = false;
startTime = 0;
printTime(Date.now())
applyStyles(true)
}
function applyStyles(isReset) {
startstopbutton.value = running ? 'Stop' : 'Start';
document.getElementById("outputt").classList.remove('red', 'green')
if (!isReset) {
document.getElementById("outputt").classList.add(running ? 'red' : 'green')
}
}
function startstop() {
running = !running;
applyStyles();
if (running) {
if (startTime) {
const diff = Date.now() - lastTime;
startTime = startTime + diff;
} else {
startTime = Date.now()
}
updateTimer(startTime);
} else {
lastTime = Date.now()
logTime();
}
}
function printTime(startTime) {
let differenceInMillis = Date.now() - startTime;
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
}
function updateTimer(startTime) {
if (running == true) {
printTime(startTime)
requestAnimationFrame(() => updateTimer(startTime));
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
.red {
background-color: #2DB37B
}
.green {
background-color: #B3321B
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();" />
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
推荐阅读
- javascript - chrome 如何将解释的 javascript 功能分配给它的小部件?
- gitlab - Gitlab Pipeline - 如何检查正在运行的实例的日志?
- angular - Angular(离子):使用循环渲染组件:组件的视图不更新
- asp.net - 如何修复此错误 StatusCode: 405, ReasonPhrase: 'Method Not Allowed', Version: 1.1 in Asp .Net Core
- apache-spark - 如果两个字符串之间出现子字符串,则提取两个字符串之间的字符串-Pyspark
- xamarin.forms - 使用 HotRestart 的本机崩溃
- php - 在我的 PHP 网页上显示上传 Amazon S3 存储桶中文件夹的估计上传时间
- java - 如何在括号“)(”上拆分字符串?
- c++ - 我将如何使用 C++ 将纯文本文件中的单词存储到数组中?
- java - Tomcat 管理器中应用程序的运行状态为 true 但找不到 404?