Check if a key is down?

2019-01-09 02:17发布

Is there a way to detect if a key is currently down in JavaScript?

I know about the "keydown" event, but that's not what I need. Some time AFTER the key is pressed, I want to be able to detect if it is still pressed down.

P. S. The biggest issue seems to be that after some period of time the key begins to repeat, firing off keydown and keyup events like a fiend. Hopefully there is just a simple isKeyDown(key) function, but if not then this issue will need to be overcome / worked around.

12条回答
该账号已被封号
2楼-- · 2019-01-09 02:29

Is there a way to detect if a key is currently down in JavaScript?

Nope. The only possibility is monitoring each keyup and keydown and remembering.

after some period of time the key begins to repeat, firing off keydown and keyup events like a fiend.

It shouldn't. You'll definitely get keypress repeating, and in many browsers you'll also get repeated keydown, but if keyup repeats, it's a bug.

Unfortunately it is not a completely unheard-of bug: on Linux, Chromium, and Firefox (when it is being run under GTK+, which it is in popular distros such as Ubuntu) both generate repeating keyup-keypress-keydown sequences for held keys, which are impossible to distinguish from someone hammering the key really fast.

查看更多
爷的心禁止访问
3楼-- · 2019-01-09 02:31

I know this is very old question, however there is a very lightweight (~.5Kb) JavaScript library that effectively "patches" the inconsistent firing of keyboard event handlers when using the DOM API.

The library is Keydrown.

Here's the operative code sample that has worked well for my purposes by just changing the key on which to set the listener:

kd.P.down(function () {
  console.log('The "P" key is being held down!');
});

kd.P.up(function () {
  console.clear();
});

// This update loop is the heartbeat of Keydrown
kd.run(function () {
  kd.tick();
});

I've incorporated Keydrown into my client-side JavaScript for a proper pause animation in a Red Light Green Light game I'm writing. You can view the entire game here. (Note: If you're reading this in the future, the game should be code complete and playable :-D!)

I hope this helps.

查看更多
戒情不戒烟
4楼-- · 2019-01-09 02:38

In addition to using keyup and keydown listeners to track when is key goes down and back up, there are actually some properties that tell you if certain keys are down.

window.onmousemove = function (e) {
  if (!e) e = window.event;
  if (e.shiftKey) {/*shift is down*/}
  if (e.altKey) {/*alt is down*/}
  if (e.ctrlKey) {/*ctrl is down*/}
  if (e.metaKey) {/*cmd is down*/}
}

This are available on all browser generated event objects, such as those from keydown, keyup, and keypress, so you don't have to use mousemove.

I tried generating my own event objects with document.createEvent('KeyboardEvent') and document.createEvent('KeyboardEvent') and looking for e.shiftKey and such, but I had no luck.

I'm using Chrome 17 on Mac

查看更多
We Are One
5楼-- · 2019-01-09 02:38

Other people have asked this kind of question before (though I don't see any obvious dupes here right now).

I think the answer is that the keydown event (and its twin keyup) are all the info you get. Repeating is wired pretty firmly into the operating system, and an application program doesn't get much of an opportunity to query the BIOS for the actual state of the key.

What you can do, and perhaps have to if you need to get this working, is to programmatically de-bounce the key. Essentially, you can evaluate keydown and keyup yourself but ignore a keyupevent if it takes place too quickly after the last keydown... or essentially, you should delay your response to keyup long enough to be sure there's not another keydown event following with something like 0.25 seconds of the keyup.

This would involve using a timer activity, and recording the millisecond times for previous events. I can't say it's a very appealing solution, but...

查看更多
仙女界的扛把子
6楼-- · 2019-01-09 02:39

I don't believe there is anything like an isKeyDown function, but you could write your own.

Basically, create an array whose length is the number of keys you want to monitor. Then using the documents/pages/controls keyUp and keyDown events, update the array with that key's state.

Then write a function that checks if a certain key is down and returns a bool.

var keyEnum = { W_Key:0, A_Key:1, S_Key:2, D_Key:3 };
var keyArray = new Array(4);

function onKeyDown()
{
    // Detect which key was pressed
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = true;
    // Repeat for each key you care about...
}

function onKeyUp()
{
    // Detect which key was released
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = false;
    // Repeat for each key you care about...
}

function isKeyDown(key)
{
    return keyArray[key];
}

That should accomplish what you want.

查看更多
做个烂人
7楼-- · 2019-01-09 02:39

Ended up here to check if there was something builtin to the browser already, but it seems there isn't. This is my solution (very similar to Robert's answer):

"use strict";

let is_key_down = (() => {
    let state = {};

    window.addEventListener('keyup', (e) => state[e.key] = false);
    window.addEventListener('keydown', (e) => state[e.key] = true);

    return (key) => state.hasOwnProperty(key) && state[key] || false;
})();

You can then check if a key is pressed with is_key_down('ArrowLeft').

查看更多
登录 后发表回答