响应秒表的长按事件

问题描述 投票:0回答:3

我一直在为这个问题苦苦挣扎。在在这里创建这篇文章之前,我在整个社区中进行了搜索,并且在 React 中看到了很多针对长按事件的解决方案,但每个人都只解决了单击按钮事件。

我正在为魔方制作一个秒表。我需要做的是以下步骤:

  1. 用户必须按住空格键两秒钟才能“好”;
  2. 一旦用户“好”,在他释放空格键的那一刻,秒表开始;
  3. 完成魔方后,他再次按下空格键来停止秒表。

P.S-1 : 如果秒表没有运行并且用户只需按空格键(不按住),则不会发生任何事情!仅当用户按住空格键至少两秒然后然后释放它时,秒表才会启动。

现在,我的问题是我应该查看的所有事件(开始和停止)都在 JavaScript 中的“keydown”和“keyup”侦听器下。我已经尝试了很多不同的解决方案来管理 JS 中的超时本机函数,但正如我所说,如果秒表停止并且用户只需按空格键,我不应该执行任何操作。

我尝试使用 useState 和 useRef 钩子来控制超时并检查空格键是刚刚按下还是长按。再说一遍,我的问题是一旦这两个事件处于“keydown”侦听器下,我不知道如何管理它。

我希望你们能帮助我,这意义重大!

提前谢谢您。

P.S-2:我正在使用 TypeScript!

javascript reactjs react-hooks long-press
3个回答
0
投票

编辑: 我忘记了 keydown 在按住时会触发多次,请查看下面的示例,只需检查该键是否是“重复”键。我必须使用 useRef 才能使其正常工作,但应该为其余逻辑奠定良好的基础:

const timestamp = useRef(0);

const spacebarPress = (e) => {
  // exit if the key is not spacebar or is the same key as last pressed
  if (e.keyCode !== 32 || e.repeat) return; 
  timestamp.current = Date.now();
}

const spacebarRelease = (e) => {
  if (e.keyCode !== 32) {
    return; // exit if the key is not spacebar
  }
  const pressed = timestamp.current, released = Date.now();
  if (released - pressed < 2000)
    return; // less than 2 seconds have passed since pressing
  // ... your logic here, spacebar was pressed for two seconds.
}

我通常倾向于尽可能避免 setTimeout,在我看来,它不是很可靠并且调试起来很痛苦。

应该可以帮助您完成大部分工作,只需在计时器运行时添加不同的按键按下/按下事件,如果

e.repeat
阻止计时器再次暂停。


0
投票

我正在尝试使用以下代码解决这个问题:

  useEffect(() => {
    document.addEventListener("keydown", handleKeyDown);
    document.addEventListener("keyup", handleKeyUp);

    return () => {
      removeEventListener("keydown", handleKeyDown);
      removeEventListener("keyup", handleKeyUp);
    };
  }, []);

  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.key !== " ") {
      return;
    }

    timeRef.current = Date.now();
    setTimestamp(Date.now());
  };

  const handleKeyUp = (e: KeyboardEvent) => {
    if (e.key !== " ") {
      return;
    }

    const pressed = timestamp;
    const released = Date.now();

    if (released - pressed < 2000) {
      return;
    }
  };

由于某种原因,时间戳状态始终为 0(默认状态)。我尝试过使用 useRef 代替,但它也不起作用。


0
投票

你最终弄清楚了吗?

© www.soinside.com 2019 - 2024. All rights reserved.