You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取按键释放的准确时机?JS的keyup事件精度不足

Fixing the Keyup Timestamp Quirk When Holding Keys Down

Hey there, I’ve run into this exact head-scratcher before—totally confusing when you first notice that your keyup timestamp never seems to be more than 500ms or so after keydown, even if you held the key for 10 seconds! Let’s break down what’s going on and how to fix it.

Why This Happens

The issue boils down to how browsers handle repeated key presses: when you hold a key down, the browser doesn’t just fire one keydown event—it fires a sequence of them. The first keydown happens when you press the key, then after a short delay (usually ~500ms, matching your system’s key repeat settings), it starts firing repeated keydown events at a faster interval.

When you finally release the key, the keyup event only associates itself with the last repeated keydown event, not the initial one. That’s why the time difference between keyup and that last keydown is only a few hundred ms max—even if you held the key for ages.

The Solution: Track the Initial Keydown Time

To get the actual duration the key was held, you need to ignore the repeated keydown events and only record the timestamp of the first one. Here’s a simple implementation:

// Track if the key is already held down
let isKeyActive = false;
let initialPressTime;

document.addEventListener('keydown', (event) => {
  // Only record the first keydown, not repeats
  if (!isKeyActive) {
    isKeyActive = true;
    initialPressTime = event.timeStamp;
    console.log('First keydown at:', initialPressTime);
  }
});

document.addEventListener('keyup', (event) => {
  if (isKeyActive) {
    isKeyActive = false;
    const releaseTime = event.timeStamp;
    const actualHoldDuration = releaseTime - initialPressTime;
    console.log('Actual hold duration:', actualHoldDuration + 'ms');
  }
});

Handling Multiple Simultaneous Keys

If your app needs to support holding multiple keys at once, you’ll want to track each key’s state individually using an object instead of a single boolean:

// Track state for each unique key
const keyTracker = {};

document.addEventListener('keydown', (event) => {
  const keyCode = event.code; // Use code for consistent key identification
  if (!keyTracker[keyCode]) {
    keyTracker[keyCode] = {
      isHeld: true,
      startTime: event.timeStamp
    };
    console.log(`Key ${keyCode} pressed at:`, keyTracker[keyCode].startTime);
  }
});

document.addEventListener('keyup', (event) => {
  const keyCode = event.code;
  if (keyTracker[keyCode]?.isHeld) {
    const holdDuration = event.timeStamp - keyTracker[keyCode].startTime;
    console.log(`Key ${keyCode} held for:`, holdDuration + 'ms');
    // Clean up the tracker entry
    delete keyTracker[keyCode];
  }
});

Quick Notes

  • For even more precise timing, you can replace event.timeStamp with performance.now()—both are relative timestamps, but performance.now() often has slightly higher precision in some browsers.
  • Different operating systems and browsers might have slightly different key repeat delays, but this logic works consistently across all major platforms.

内容的提问来源于stack exchange,提问作者OMGsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:09:04