Home > Enterprise >  is there a way to somehow hold a keypress in js
is there a way to somehow hold a keypress in js

Time:07-27

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>

  • Related