So what I'm trying to do is to self replicate a Rubik's cube timer like cstimer.net
What I do is detect a spacebar key press and it is meant to start a timer, however it only adds 1 millisecond at a press instead of a continuous timer, what I'm thinking is to find a way to continuously hold the spacebar if the javascript file, how do I fix this?
const minute = document.getElementById("minute");
const second = document.getElementById("second");
const millisecond = document.getElementById("millisecond");
let ms = 0;
let sec = 0;
let min = 0;
const start = () => console.log("start")
document.addEventListener('keypress', function(event) {
if (event.code === "Space") {
timeoutId = setTimeout(function() {
ms = parseInt(ms);
sec = parseInt(sec);
min = parseInt(min);
ms ;
if (ms == 100) {
sec = sec 1;
ms = 0;
}
if (sec == 60) {
min = min 1;
sec = 0;
}
if (ms < 10) {
ms = '0' ms;
}
if (sec < 10) {
sec = '0' sec;
}
if (min < 10) {
min = '0' min;
}
minute.innerHTML = min;
second.innerHTML = sec;
millisecond.innerHTML = ms;
start();
}, 10);
}
});
<span id="minute"></span>
<span id="second"></span>
<span id="millisecond"></span>
CodePudding user response:
setTimeout
only triggers the timer function once; instead you should use requestAnimationFrame
to update the timer every repaint.
Let's also fix the unreliableness of the timer implementation as mentioned by @gre_gor. Instead of adding to the ms
counter each time, store the initial time (via Date.now()
) and then calculate the elapsed milliseconds each time.
const minute = document.getElementById("minute");
const second = document.getElementById("second");
const millisecond = document.getElementById("millisecond");
let initialTime;
function timer() {
let ms = Date.now() - initialTime;
let sec = Math.floor(ms / 1000);
ms = ms % 1000;
let min = Math.floor(sec / 60);
sec = sec % 60;
minute.innerHTML = min;
second.innerHTML = sec;
millisecond.innerHTML = ms;
requestAnimationFrame(timer);
}
document.addEventListener('keypress', function(event) {
if (event.code === "Space") {
initialTime = Date.now();
requestAnimationFrame(timer);
}
});
<span id="minute"></span>
<span id="second"></span>
<span id="millisecond"></span>
If you need to stop the timer, it's a bit trickier for a rAF loop than for setTimeout - see How to stop a requestAnimationFrame recursion/loop?.
CodePudding user response:
This one is more precise and has animation built in. (You could be even more precise using function like performance.now())
const timer = document.getElementById("timer");
var start_time = null;
var state = "paused";
function draw() {
if (state == "playing") {
var diff = Date.now() - start_time
var time = (new Date(diff).toISOString().slice(11, 23));
timer.innerHTML = time;
}
}
function loop() {
draw();
requestAnimationFrame(loop)
}
loop();
document.addEventListener('keypress', function(event) {
if (event.code === "Space") {
if (state == "paused") {
state = "playing";
start_time = Date.now()
return;
}
if (state == "playing") {
state = "paused";
start_time = null;
return;
}
}
});
#timer {
font-size:48px;
}
Press [space]<br>
<span id="timer"></span>