简体   繁体   English

如何在js中使用键盘事件创建计数计时器

[英]How to create countup timer with keyboard events in js

I am creating a program where the timer starts when i hit "keyup" and stops when i hit "keydown" and resets the timer when i hit "keydown" next time.我正在创建一个程序,当我点击“keyup”时计时器开始并在我点击“keydown”时停止并在我下次点击“keydown”时重置计时器。

const Timer = () => {
  const [timer, setTimer] = useState(0);
  let state = 0;
  let isFired = false;
  const increment = useRef(null);

  useEffect(() => {
    window.addEventListener('keydown', (e) => {
      if (isFired) {
        if (e.code === 'Space' && state === 2) {
          e.stopPropagation();
          isFired = false;
          handleReset();
        }

        if (e.code === 'Space' && state === 1) {
          clearInterval(increment.current);
          state = 2;
        }
      }
    });

    window.addEventListener('keyup', (e) => {
      if (!isFired) {
        if (e.code === 'Space' && state === 0) {
          isFired = true;
          state = 1;
          handleStart();
        }
      }
    });

    return () => {
      window.removeEventListener('keydown', handleReset);
      window.removeEventListener('keyup', handleStart);
    };
  }, []);

  const handleStart = () => {
    increment.current = setInterval(() => {
    // DON'T COPY THIS BIT
      setTimer((timer) => timer + 10);
    }, 10);
  };

  const handleReset = () => {
    clearInterval(increment.current);
    setTimer(0);
    state = 0;
  };
  // DON'T COPY THIS BIT

  const formatTime = () => {
    console.log(timer);
    const getMilliSeconds = `0${timer % 60}`.slice(-2);
    const seconds = `${Math.floor(timer / 60)}`;
    const getSeconds = `0${seconds % 60}`.slice(-2);
    const getMinutes = `0${Math.floor(timer / 3600)}`.slice(-2);

    // return `${getHours} : ${getMinutes} : ${getSeconds}`;
    if (getMinutes === '00') {
      return `${getSeconds}.${getMilliSeconds}`;
    } else {
      return `${getMinutes} : ${getSeconds} : ${getMilliSeconds} `;
    }
  };

  // const formatTime = () => {
  //   // const milliSeconds = `0${}`;
  //   const seconds = `0${Math.floor(timer / 100)}`;
  //   const minute = `0${Math.floor(timer / 3600)}`.slice(-2);

  //   return `${minute}.${seconds}`;
  // };

  return (
    <div className="Timer">
      <h1>{formatTime()}</h1>
    </div>
  );
};

i have tried this so far it works most of the time but sometimes it gets glitchy and i know the time is not formated properly and also the increment is also wrong.到目前为止,我已经尝试过这种方法,它大部分时间都可以工作,但有时会出现故障,而且我知道时间格式不正确,而且增量也是错误的。 Sometimes it stops on the "keydown" and fires the "keyup" in the same stroke making it reset the timer starting from zero I don't exactly know that if it fires keyup on the same stroke but it seems like it does有时它会在“keydown”上停止并在同一笔划中触发“keyup”,使其从零开始重置计时器我不完全知道它是否在同一笔划上触发 keyup 但似乎确实如此

this is a link to what i have done so far timer这是我到目前为止所做的工作的链接计时器

I checked your code and found it needs too many changes.我检查了您的代码,发现它需要进行太多更改。

  1. You are using state and isFired as variables only but you need their persisted values on rerendering.您仅将stateisFired用作变量,但在重新渲染时需要它们的持久值。 Therefore, these must be states.因此,这些必须是状态。
  2. You are not unbinding the same listener which you binded on keyup and keydown .您没有取消绑定在keyupkeydown上绑定的同一个侦听器。
  3. As per your current code, your timer will start on 1st keyup and then next keydown it will stop as such where it was.根据你的当前的代码,你的计时器将开始在1日keyup ,然后接下来keydown就会停止这样它在哪里。 Now, on next keydown it will reset to 0 and then on keyup , again timer will start from 0.现在,在下一次keydown ,它将重置为 0,然后在keyup ,再次计时器将从 0 开始。

I modified your code and see working changes here,我修改了你的代码并在这里看到了工作变化,

https://codesandbox.io/s/xenodochial-shannon-im8zt?file=/src/App.js https://codesandbox.io/s/xenodochial-shannon-im8zt?file=/src/App.js

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM