重复单击开始/重置按钮时出现秒表时间问题

问题描述 投票:0回答:2

当我点击开始时,计数开始,开始按钮隐藏并显示暂停和重置按钮。如果我反复单击开始和重置,计数将不再正确计数,重置按钮和暂停按钮甚至不再重要。

var c = 0;
var t;

function count() {
  document.getElementById("count").innerHTML = c;
  c = c + 1;
  t = setTimeout(count, 1000);
}

function start() {
  count();
  document.getElementById("startb").style.display = "none";
  document.getElementById("pauseb").style.display = "inline";
}

function pause() {
  clearTimeout(t);
  document.getElementById("startb").style.display = "inline";
  document.getElementById("pauseb").style.display = "none";
  document.getElementById("startb").innerHTML = "Resume";
  document.getElementById("resetb").style.display = "inline";
}

function reset() {
  c = 0;
  clearTimeout(t);
  document.getElementById("count").innerHTML = c;
  document.getElementById("startb").style.display = "inline";
  document.getElementById("startb").innerHTML = "Start";
  document.getElementById("pauseb").style.display = "none";
  document.getElementById("resetb").style.display = "none";
}
* {
  margin: 0;
  padding: 0;
  font-family: Arial;
}

body {
  background-color: #333;
  color: black;
}

button {
  width: 100px;
  height: 30px;
  line-height: 30px;
  text-align: center;
  color: #000;
  background-color: #c3c3c3;
  border: 1px solid #000;
}

#count {
  font-size: 175px;
}

#startb {
  background-color: #800080;
  border-color: #220022;
  color: #2e002e;
}

#pauseb {
  display: none;
  background-color: black;
  color: #b6b6b6;
}

#resetb {
  display: none;
  background-color: red;
  color: #3b0000;
  border-color: #3b0000;
  font-weight: bold;
}

#lapb {
  display: none;
  background-color: #008800;
  color: black;
  border-color: darkgreen;
  font-weight: bold;
}
<h1>Stopwatch</h1>
<span id="count">0</span><br />
<button id="startb" onClick="start()">Start</button>
<button id="pauseb" onClick="pause()">Pause</button>
<button id="resetb" onClick="reset()">Reset</button>
<button id="lapb" onClick="lap()">Lap</button>

我还没有尝试过任何事情,我猜测正在处理启动函数的多个实例,我想如果其他地方的语句可以阻止这种情况。

javascript
2个回答
2
投票
    当需要频繁更新 UI 时,不要使用
  • setInterval
    (特别是不要设置如此昂贵的 
    ms 间隔)。你不想用 setInterval 来控制主线程,而是使用性能上的绝对赢家,那就是 Window.requestAnimationFrame
  • 在 HTML 中,不要使用 ID。为什么不在一个页面上放置多个手表呢?如果您使用 ID-s,您的代码将仅与一个元素紧密耦合。使用类来代替
  • 避免使用 JS 中的
  • Element.style
    ,而是使用 Element.classList 方法,如 
    .add()
    .remove()
    ,甚至更简单地使用 
    data-*
     属性(如:
    el.dataset.stopwatch = "some state name"
这是一个更好且

高性能的秒表示例,可预览h+:m:s.ms


const pad = (int, pad) => String(int).padStart(pad, "0"); const stopwatch = (el) => { const elCount = el.querySelector(".stopwatch-count"); const elStart = el.querySelector(".stopwatch-start"); const elResume = el.querySelector(".stopwatch-resume"); const elPause = el.querySelector(".stopwatch-pause"); const elReset = el.querySelector(".stopwatch-reset"); let timeStart; let timeElapsed; let raf; const draw = () => { const mil = timeElapsed % 1000; const sec = Math.floor(timeElapsed / 1000 % 60); const min = Math.floor(timeElapsed / 1000 / 60 % 60); const hou = Math.floor(timeElapsed / 1000 / 60 / 60); elCount.textContent = `${pad(hou)}:${pad(min, 2)}:${pad(sec, 2)}.${pad(mil, 3)}`; }; const count = () => { timeElapsed = Date.now() - timeStart; draw(); raf = requestAnimationFrame(count); }; const start = () => { el.dataset.stopwatch = "running"; timeStart = Date.now() - timeElapsed; count(); }; const pause = () => { el.dataset.stopwatch = "paused"; cancelAnimationFrame(raf); }; const reset = () => { el.dataset.stopwatch = "init"; cancelAnimationFrame(raf); timeStart = 0; timeElapsed = 0; timeDiff = 0; draw(); }; // Events: elStart.addEventListener("click", start); elPause.addEventListener("click", pause); elResume.addEventListener("click", start); elReset.addEventListener("click", reset); // Init: reset(); }; // Initialize: document.querySelectorAll(".stopwatch").forEach(stopwatch);
* {
  box-sizing: border-box;
  margin: 0;
  font-family: Arial;
}

button {
  border: 1px solid #000;
  color: #fff;
  min-width: 5rem;
  padding: 0.6em;
}

.stopwatch-count {
  font-size: 3rem;
}

.stopwatch-start {
  background-color: green;
}

.stopwatch-resume {
  display: none;
  background-color: blue;
}

.stopwatch-pause {
  display: none;
  background-color: black;
}

.stopwatch-reset {
  display: none;
  background-color: red;
}

[data-stopwatch="running"] .stopwatch-start {
  display: none;
}

[data-stopwatch="running"] .stopwatch-pause {
  display: initial;
}

[data-stopwatch="paused"] .stopwatch-start,
[data-stopwatch="paused"] .stopwatch-pause {
  display: none;
}

[data-stopwatch="paused"] .stopwatch-reset {
  display: initial;
}

[data-stopwatch="paused"] .stopwatch-resume {
  display: initial;
}
<div class="stopwatch">
  <span class="stopwatch-count"></span><br />
  <button class="stopwatch-start">Start</button>
  <button class="stopwatch-resume">Resume</button>
  <button class="stopwatch-pause">Pause</button>
  <button class="stopwatch-reset">Reset</button>
</div>

并且适用于单个页面上任意数量的秒表。


-1
投票
试试这个。精度可达毫秒

var startTime; var elapsedTime = 0; var timerInterval; function start() { startTime = Date.now() - elapsedTime; if (!timerInterval) { timerInterval = setInterval(updateTime, 10); } } function pause() { clearInterval(timerInterval); timerInterval = null; } function reset() { clearInterval(timerInterval); timerInterval = null; elapsedTime = 0; var formattedTime = formatTime(elapsedTime); document.querySelector(".time").textContent = formattedTime; } function updateTime() { var currentTime = Date.now(); elapsedTime = currentTime - startTime; var formattedTime = formatTime(elapsedTime); document.querySelector(".time").textContent = formattedTime; } function formatTime(time) { var hours = Math.floor(time / 3600000); var minutes = Math.floor((time % 3600000) / 60000); var seconds = Math.floor((time % 60000) / 1000); var milliseconds = Math.floor((time % 1000) / 10); return ( pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "." + pad(milliseconds, 2) ); } function pad(value, count) { var padding = ""; for (var i = 0; i < count; i++) { padding += "0"; } return (padding + value).slice(-count); }
.container {
  text-align: center;
  margin-top: 100px;
}

.time {
  font-size: 48px;
  margin-bottom: 20px;
}

.buttons {
  margin-top: 20px;
}
<!DOCTYPE html>
<html>

<head>
  <title>Stopwatch</title>
</head>

<body>
  <div class="container">
    <div class="time">00:00:00</div>
    <div class="buttons">
      <button onclick="start()">Start/Resume</button>
      <button onclick="pause()">Pause</button>
      <button onclick="reset()">Reset</button>
    </div>
  </div>
</body>

</html>

编辑:

请求动画帧不是此用例的正确解决方案,原因如下:

    这里没有动画。
  1. 即使有动画正在进行
  2. requestAnimationFrame
    在后台选项卡或隐藏的 iframe 标签中运行时调用也会暂停,这对于秒表应用程序来说并不理想

MDN

 上了解有关 requestAnimationFrame 的更多信息
    

© www.soinside.com 2019 - 2024. All rights reserved.