Reputation: 1
I want to make a stopwatch in JavaScript that could count milliseconds, seconds, minutes, and hours. The problem is that it seems to not go at the proper speed, meaning that when I compare it to other timers, it gradually becomes slower than them (i.e the speed at which the timer is counting slows down over time). So suddenly, there are 5-second differences, then it becomes 7-second differences, and so on. Any help would be appreciated. My code for Stopwatch.
var hr = 0;
var min = 0;
var sec = 0;
var count = 0;
var Startbutton = document.getElementById("Start");
var timer = false;
function start() {
Startbutton.disabled = true; //this wil help to avoid multiple clicking on function
timer = true;
stopwatch();
}
function stop() {
timer = false;
Startbutton.disabled = false;
}
function reset() {
timer = false;
Startbutton.disabled = false;
min = 0;
hr = 0;
sec = 0;
count = 0;
document.getElementById("hr").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("count").innerHTML = "00";
}
function stopwatch() {
if (timer) {
++count;
if (count > 99) {
++sec;
count = 0;
}
if (sec > 59) {
min++;
sec = 0;
}
if (min > 59) {
hr++;
min = 0;
sec = 0;
}
if (hr > 23) {
hr = 0;
sec = 0;
min = 0;
}
var hrString = hr;
var minString = min;
var secString = sec;
var countString = count;
if (hr < 10) {
hrString = "0" + hrString;
}
if (min < 10) {
minString = "0" + minString;
}
if (sec < 10) {
secString = "0" + secString;
}
if (count < 10) {
countString = "0" + countString;
}
document.getElementById("hr").innerHTML = hrString;
document.getElementById("min").innerHTML = minString;
document.getElementById("sec").innerHTML = secString;
document.getElementById("count").innerHTML = countString;
console.log("hello");
setTimeout(stopwatch, 10);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Stopwatch</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="container">
<div id="time">
<span class="digit" id="hr">00</span>
<span class="txt">Hr</span>
<span class="digit" id="min">00</span>
<span class="txt">Min</span>
<span class="digit" id="sec">00</span>
<span class="txt">Sec</span>
<span class="digit" id="count">00</span>
</div>
<div id="btn-container">
<button class="btn" id="Start" onclick="start()">Start</button>
<button class="btn" id="Stop" onclick="stop()">Stop</button>
<button class="btn" id="Reset" onclick="reset()">Reset</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Upvotes: 0
Views: 722
Reputation: 39
You should take time from system clock. Otherwise time will be relative in your code :) The code below you can inspect.
var hr = 0;
var min = 0;
var sec = 0;
var count = 0;
var Startbutton = document.getElementById("Start");
var startTime = Date.now();
var timer = false;
function start() {
Startbutton.disabled = true; //this wil help to avoid multiple clicking on function
timer = true;
startTime = Date.now();
stopwatch();
}
function stop() {
timer = false;
Startbutton.disabled = false;
}
function reset() {
timer = false;
Startbutton.disabled = false;
min = 0;
hr = 0;
sec = 0;
count = 0;
document.getElementById("hr").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("count").innerHTML = "00";
}
function stopwatch() {
if (timer) {
var elapsedTime = Date.now() - startTime;
var hr = Math.floor(elapsedTime / (60 * 60 * 1000) % 24).toString().padStart(2, '0');
var min = Math.floor(elapsedTime / (60 * 1000) % 60).toString().padStart(2, '0');
var sec = Math.floor(elapsedTime / 1000 % 60).toString().padStart(2, '0');
var msec = Math.floor(elapsedTime % 1000).toString().padStart(2, '0');
document.getElementById("hr").innerHTML = hr;
document.getElementById("min").innerHTML = min;
document.getElementById("sec").innerHTML = sec;
document.getElementById("count").innerHTML = msec;
setTimeout(stopwatch, 10);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Stopwatch</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="container">
<div id="time">
<span class="digit" id="hr">00</span>
<span class="txt">Hr</span>
<span class="digit" id="min">00</span>
<span class="txt">Min</span>
<span class="digit" id="sec">00</span>
<span class="txt">Sec</span>
<span class="digit" id="count">00</span>
</div>
<div id="btn-container">
<button class="btn" id="Start" onclick="start()">Start</button>
<button class="btn" id="Stop" onclick="stop()">Stop</button>
<button class="btn" id="Reset" onclick="reset()">Reset</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Upvotes: 0
Reputation: 19495
Because you don't take into account the time it takes for it to draw the html. Need to re-design to use system clock. See my example.
var hr = 0;
var min = 0;
var sec = 0;
var count = 0;
var Startbutton = document.getElementById("Start");
var timer = false;
var start_time;
function start() {
Startbutton.disabled = true; //this wil help to avoid multiple clicking on function
timer = true;
start_time = (new Date()).getTime();
stopwatch();
}
function stop() {
timer = false;
start_time = null;
Startbutton.disabled = false;
}
function reset() {
timer = false;
start_time = null;
Startbutton.disabled = false;
min = 0;
hr = 0;
sec = 0;
count = 0;
document.getElementById("hr").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("count").innerHTML = "00";
}
function stopwatch() {
var now = (new Date()).getTime();
var diff = now - start_time;
if (timer) {
var str_time = (new Date(diff).toISOString().slice(11, 23)); // 👉️ 15:00:00.000
var hrString = ""+str_time.substring(0,2);
var minString = ""+str_time.substring(3,5);
var secString = ""+str_time.substring(6,8);
var countString =""+ str_time.substring(9,11);
document.getElementById("hr").innerHTML = hrString;
document.getElementById("min").innerHTML = minString;
document.getElementById("sec").innerHTML = secString;
document.getElementById("count").innerHTML = countString;
//console.log("hello");
requestAnimationFrame(stopwatch)
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Stopwatch</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="container">
<div id="time">
<span class="digit" id="hr">00</span>
<span class="txt">Hr</span>
<span class="digit" id="min">00</span>
<span class="txt">Min</span>
<span class="digit" id="sec">00</span>
<span class="txt">Sec</span>
<span class="digit" id="count">00</span>
</div>
<div id="btn-container">
<button class="btn" id="Start" onclick="start()">Start</button>
<button class="btn" id="Stop" onclick="stop()">Stop</button>
<button class="btn" id="Reset" onclick="reset()">Reset</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Upvotes: 1