0

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>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 1
    [keydown event](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event) and [keyup event](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event) – gre_gor Jul 26 '22 at 19:48
  • keydown vs keypress vs keyup https://thisthat.dev/keydown-vs-keypress-vs-keyup/ – GrafiCode Jul 26 '22 at 19:48
  • And counting time like that in unreliable. You aren't guaranteed that `setTimeout` triggers exactly in 10 ms. Also you seem to count 1 ms every 10 ms. – gre_gor Jul 26 '22 at 19:52
  • How can i count it reliably? – DamilolaOwonibi Jul 26 '22 at 19:56
  • I made you a snippet. It would have been nice if you had done that so we had a [mcve] – mplungjan Jul 26 '22 at 19:57
  • Actually those aren't milliseconds (1/1000 s) as the `ms` variable implies. Those are centiseconds (1/100 s). And that `setTimeout` is completely pointless, as how much time you need to add depends on the frequency that `keypress` triggers and not how much you delay it. – gre_gor Jul 26 '22 at 20:17

2 Answers2

0

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?.

SuperStormer
  • 4,997
  • 5
  • 25
  • 35
0

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>
IT goldman
  • 14,885
  • 2
  • 14
  • 28