如何使用 JavaScript 检测是否同时按下多个键?

发布于 2024-10-20 13:58:35 字数 224 浏览 5 评论 0原文

我正在尝试开发一个 JavaScript 游戏引擎,并且遇到了这个问题:

  • 当我按 SPACE 时,角色会跳跃。
  • 当我按 时,角色向右移动。

问题是,当我按向右然后按空格时,角色会跳跃然后停止移动。

我使用 keydown 函数来按下按键。如何检查是否同时按下了多个键?

I'm trying to develop a JavaScript game engine and I've came across this problem:

  • When I press SPACE the character jumps.
  • When I press the character moves right.

The problem is that when I'm pressing right and then press space, the character jumps and then stops moving.

I use the keydown function to get the key pressed. How can I check if there are multiple keys pressed at once?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

女中豪杰 2024-10-27 13:58:36

注意:keyCode 现已弃用。< /strong>

如果您理解这个概念,多次击键检测很容易

。我的做法是这样的:

var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
    e = e || event; // to deal with IE
    map[e.keyCode] = e.type == 'keydown';
    /* insert conditional here */
}

这段代码非常简单:由于计算机一次只传递一次击键,因此创建一个数组来跟踪多个键。然后可以使用该数组一次检查一个或多个键。

只是为了解释一下,假设您按 AB,每个都会触发一个 keydown 事件来设置 map[e.keyCode]< /code> 为 e.type == keydown 的值,其计算结果为 truefalse。现在,map[65]map[66] 均设置为 true。当您松开 A 时,会触发 keyup 事件,导致相同的逻辑为 map[65] 确定相反的结果 (A) ,现在为 false,但由于 map[66] (B) 仍处于“按下”状态(它尚未触发 keyup 事件),因此它仍然是正确。

通过这两个事件,map 数组如下所示:

// keydown A 
// keydown B
[
    65:true,
    66:true
]
// keyup A
// keydown B
[
    65:false,
    66:true
]

您现在可以执行两件事:

A) 按键记录器 (example) 可以创建作为参考,供以后需要快速找出一个或多个关键代码时参考。假设您已经定义了一个 html 元素并使用变量 element 指向它。

element.innerHTML = '';
var i, l = map.length;
for(i = 0; i < l; i ++){
    if(map[i]){
        element.innerHTML += '<hr>' + i;
    }
}

注意:您可以通过元素的 id 属性轻松获取元素。

<div id="element"></div>

这将创建一个 html 元素,可以使用 element 在 javascript 中轻松引用该元素,

alert(element); // [Object HTMLDivElement]

您甚至不必使用 document.getElementById()$() 来抓取它。但出于兼容性考虑,更广泛推荐使用 jQuery 的 $()

只需确保 script 标记位于 HTML 正文之后。 优化提示:大多数大牌网站都会将script标签放在body标签之后进行优化。这是因为脚本标签会阻止进一步的元素加载,直到其脚本下载完成。将其放在内容之前可以让内容提前加载。

B(这是您感兴趣的地方) 您可以在 /*insertconditionalhere*/ 所在的位置一次检查一个或多个键,例如:

if(map[17] && map[16] && map[65]){ // CTRL+SHIFT+A
    alert('Control Shift A');
}else if(map[17] && map[16] && map[66]){ // CTRL+SHIFT+B
    alert('Control Shift B');
}else if(map[17] && map[16] && map[67]){ // CTRL+SHIFT+C
    alert('Control Shift C');
}

>编辑:这不是最易读的片段。可读性很重要,所以你可以尝试这样的方法,让眼睛更舒服:

function test_key(selkey){
    var alias = {
        "ctrl":  17,
        "shift": 16,
        "A":     65,
        /* ... */
    };

    return key[selkey] || key[alias[selkey]];
}

function test_keys(){
    var keylist = arguments;

    for(var i = 0; i < keylist.length; i++)
        if(!test_key(keylist[i]))
            return false;

    return true;
}

用法:

test_keys(13, 16, 65)
test_keys('ctrl', 'shift', 'A')
test_key(65)
test_key('A')

这样更好吗?

if(test_keys('ctrl', 'shift')){
    if(test_key('A')){
        alert('Control Shift A');
    } else if(test_key('B')){
        alert('Control Shift B');
    } else if(test_key('C')){
        alert('Control Shift C');
    }
}

(编辑结束)


此示例检查 CtrlShiftACtrlShift BCtrlShiftC

这么

简单

:)

就 根据规则,记录代码是一种很好的做法,尤其是像关键代码(例如 // CTRL+ENTER)这样的内容,这样您就可以记住它们是什么。

您还应该按照与文档相同的顺序放置关键代码(CTRL+ENTER => map[17] && map[13],而不是 map[13] & ;&地图[17])。这样,当您需要返回并编辑代码时,您就不会感到困惑。

if-else 链的陷阱

如果检查不同数量的组合(例如 CtrlShiftAltEnter 和 < kbd>CtrlEnter),将较小的组合放在较大的组合之后,否则较小的组合将覆盖较大的组合(如果它们足够相似)。示例:

// Correct:
if(map[17] && map[16] && map[13]){ // CTRL+SHIFT+ENTER
    alert('Whoa, mr. power user');
}else if(map[17] && map[13]){ // CTRL+ENTER
    alert('You found me');
}else if(map[13]){ // ENTER
    alert('You pressed Enter. You win the prize!')
}

// Incorrect:
if(map[17] && map[13]){ // CTRL+ENTER
    alert('You found me');
}else if(map[17] && map[16] && map[13]){ // CTRL+SHIFT+ENTER
    alert('Whoa, mr. power user');
}else if(map[13]){ // ENTER
    alert('You pressed Enter. You win the prize!');
}
// What will go wrong: When trying to do CTRL+SHIFT+ENTER, it will
// detect CTRL+ENTER first, and override CTRL+SHIFT+ENTER.
// Removing the else's is not a proper solution, either
// as it will cause it to alert BOTH "Mr. Power user" AND "You Found Me"

问题:“即使我没有按下按键,此组合键也会持续激活”

在处理警报或任何从主窗口获取焦点的内容时,您可能需要包含 map = []条件完成后重置数组。这是因为有些东西(例如 alert())会将焦点从主窗口移开,并导致“keyup”事件无法触发。例如:

if(map[17] && map[13]){ // CTRL+ENTER
    alert('Oh noes, a bug!');
}
// When you Press any key after executing this, it will alert again, even though you 
// are clearly NOT pressing CTRL+ENTER
// The fix would look like this:

if(map[17] && map[13]){ // CTRL+ENTER
    alert('Take that, bug!');
    map = {};
}
// The bug no longer happens since the array is cleared

问题:浏览器默认值

这是我发现的一件烦人的事情,其中​​包含解决方案:

问题:由于浏览器通常对组合键有默认操作(例如 CtrlD 激活)书签窗口,或 CtrlShiftC 在 maxthon 上激活 skynote),您可能还需要添加 return falsemap = [] 之后,这样当“复制文件”功能被置于 CtrlD 上时,您网站的用户就不会感到沮丧,改为为页面添加书签。

if(map[17] && map[68]){ // CTRL+D
    alert('The bookmark window didn\'t pop up!');
    map = {};
    return false;
}

如果不返回 false,书签窗口就会弹出,这会让用户感到沮丧。

return 语句(新)

好的,所以您并不总是想在此时退出该函数。这就是 event.preventDefault() 函数存在的原因。它的作用是设置一个内部标志,告诉解释器不允许允许浏览器运行其默认操作。之后,函数继续执行(而return将立即退出函数)。

在决定是使用 return false 还是 e.preventDefault() 之前,请先了解这种区别

event.keyCode 已弃用

用户 SeanVieira 在评论中指出 event.keyCode 已被弃用。

在那里,他给出了一个很好的替代方案:event.key,它返回被按下的键的字符串表示形式,例如 "a" 代表 A ,或 "Shift" 表示 Shift

我继续编写了一个工具来检查所述字符串。

element.oneventelement.addEventListener

使用 addEventListener 注册的处理程序可以堆叠,并按照注册的顺序调用,同时设置 .onevent 直接相当激进,会覆盖您以前拥有的任何内容。

document.body.onkeydown = function(ev){
    // do some stuff
    ev.preventDefault(); // cancels default actions
    return false; // cancels this function as well as default actions
}

document.body.addEventListener("keydown", function(ev){
    // do some stuff
    ev.preventDefault() // cancels default actions
    return false; // cancels this function only
});

.onevent 属性似乎会覆盖所有内容,并且 ev.preventDefault()return false; 的行为可能相当不可预测。

无论哪种情况,通过 addEventlistener 注册的处理程序似乎都更容易编写和推理。

Internet Explorer 的非标准实现中还有 attachEvent("oneevent",callback),但这已超出弃用范围,甚至不属于 JavaScript(它属于一种名为 的深奥语言) JScript)。尽可能避免使用多语言代码将符合您的最佳利益。

辅助类

为了解决混淆/投诉,我编写了一个执行此抽象的“类”(pastebin 链接) :

function Input(el){
    var parent = el,
        map = {},
        intervals = {};
    
    function ev_kdown(ev)
    {
        map[ev.key] = true;
        ev.preventDefault();
        return;
    }
    
    function ev_kup(ev)
    {
        map[ev.key] = false;
        ev.preventDefault();
        return;
    }
    
    function key_down(key)
    {
        return map[key];
    }

    function keys_down_array(array)
    {
        for(var i = 0; i < array.length; i++)
            if(!key_down(array[i]))
                return false;

        return true;
    }
    
    function keys_down_arguments()
    {
        return keys_down_array(Array.from(arguments));
    }
    
    function clear()
    {
        map = {};
    }
    
    function watch_loop(keylist, callback)
    {
        return function(){
            if(keys_down_array(keylist))
                callback();
        }
    }

    function watch(name, callback)
    {
        var keylist = Array.from(arguments).splice(2);

        intervals[name] = setInterval(watch_loop(keylist, callback), 1000/24);
    }

    function unwatch(name)
    {
        clearInterval(intervals[name]);
        delete intervals[name];
    }

    function detach()
    {
        parent.removeEventListener("keydown", ev_kdown);
        parent.removeEventListener("keyup", ev_kup);
    }
    
    function attach()
    {
        parent.addEventListener("keydown", ev_kdown);
        parent.addEventListener("keyup", ev_kup);
    }
    
    function Input()
    {
        attach();

        return {
            key_down: key_down,
            keys_down: keys_down_arguments,
            watch: watch,
            unwatch: unwatch,
            clear: clear,
            detach: detach
        };
    }
    
    return Input();
}

这个类并不能完成所有事情,也不能处理所有可以想象的用例。我不是图书馆人。但对于一般的交互使用来说应该没问题。

要使用此类,请创建一个实例并将其指向要与键盘输入关联的元素:

var input_txt = Input(document.getElementById("txt"));

input_txt.watch("print_5", function(){
    txt.value += "FIVE ";
}, "Control", "5");

这将执行的操作是将新的输入侦听器附加到带有 #txt 的元素(假设它是一个textarea),并为组合键 Ctrl+5 设置观察点。当 Ctrl5 都按下时,您传入的回调函数(在本例中,是一个将 "FIVE " 添加到文本区域的函数) )将被调用。该回调与名称 print_5 关联,因此要删除它,您只需使用:

input_txt.unwatch("print_5");

input_txttxt 元素分离:

input_txt.detach();

这样,如果该对象 (input_txt) 被丢弃,垃圾回收可以拾取该对象,并且不会留下旧的僵尸事件侦听器。

为了完整起见,这里是该类 API 的快速参考,以 C/Java 风格呈现,以便您知道它们返回什么以及它们期望什么参数。

Boolean key_down(字符串键);

如果 key 按下,则返回 true,否则返回 false。

布尔keys_down(字符串key1,字符串key2,...);

如果所有键 key1 .. keyN 均按下,则返回 true,否则返回 false。

void watch(字符串名称,函数回调,字符串key1,字符串key2,...);

创建一个“观察点”,以便按下所有 keyN 将触发回调

void unwatch (字符串名称);

通过名称删除所述观察点

void 清除 (void);

擦除“按键按下”缓存。相当于上面的map = {}

void 分离(void);

从父元素中分离 ev_kdownev_kup 监听器,从而可以安全地删除实例

< strong>更新 2017-12-02 为了响应将其发布到 github 的请求,我创建了一个

更新 2018-07-21 我已经使用声明式编程有一段时间了,现在这种方式是我个人最喜欢的:小提琴pastebin

一般来说,它适用于您实际想要的情况(ctrl、alt、shift),但如果您需要同时按下 a+w ,则它不会将这些方法“组合”成多键查找太困难了。


我希望这篇详尽解释的答案迷你博客对您有所帮助:)

Note: keyCode is now deprecated.

Multiple keystroke detection is easy if you understand the concept

The way I do it is like this:

var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
    e = e || event; // to deal with IE
    map[e.keyCode] = e.type == 'keydown';
    /* insert conditional here */
}

This code is very simple: Since the computer only passes one keystroke at a time, an array is created to keep track of multiple keys. The array can then be used to check for one or more keys at once.

Just to explain, let's say you press A and B, each fires a keydown event that sets map[e.keyCode] to the value of e.type == keydown, which evaluates to either true or false. Now both map[65] and map[66] are set to true. When you let go of A, the keyup event fires, causing the same logic to determine the opposite result for map[65] (A), which is now false, but since map[66] (B) is still "down" (it hasn't triggered a keyup event), it remains true.

The map array, through both events, looks like this:

// keydown A 
// keydown B
[
    65:true,
    66:true
]
// keyup A
// keydown B
[
    65:false,
    66:true
]

There are two things you can do now:

A) A Key logger (example) can be created as a reference for later when you want to quickly figure out one or more key codes. Assuming you have defined an html element and pointed to it with the variable element.

element.innerHTML = '';
var i, l = map.length;
for(i = 0; i < l; i ++){
    if(map[i]){
        element.innerHTML += '<hr>' + i;
    }
}

Note: You can easily grab an element by its id attribute.

<div id="element"></div>

This creates an html element that can be easily referenced in javascript with element

alert(element); // [Object HTMLDivElement]

You don't even have to use document.getElementById() or $() to grab it. But for the sake of compatibility, use of jQuery's $() is more widely recommended.

Just make sure the script tag comes after the body of the HTML. Optimization tip: Most big-name websites put the script tag after the body tag for optimization. This is because the script tag blocks further elements from loading until its script is finished downloading. Putting it ahead of the content allows the content to load beforehand.

B (which is where your interest lies) You can check for one or more keys at a time where /*insert conditional here*/ was, take this example:

if(map[17] && map[16] && map[65]){ // CTRL+SHIFT+A
    alert('Control Shift A');
}else if(map[17] && map[16] && map[66]){ // CTRL+SHIFT+B
    alert('Control Shift B');
}else if(map[17] && map[16] && map[67]){ // CTRL+SHIFT+C
    alert('Control Shift C');
}

Edit: That isn't the most readable snippet. Readability's important, so you could try something like this to make it easier on the eyes:

function test_key(selkey){
    var alias = {
        "ctrl":  17,
        "shift": 16,
        "A":     65,
        /* ... */
    };

    return key[selkey] || key[alias[selkey]];
}

function test_keys(){
    var keylist = arguments;

    for(var i = 0; i < keylist.length; i++)
        if(!test_key(keylist[i]))
            return false;

    return true;
}

Usage:

test_keys(13, 16, 65)
test_keys('ctrl', 'shift', 'A')
test_key(65)
test_key('A')

Is this better?

if(test_keys('ctrl', 'shift')){
    if(test_key('A')){
        alert('Control Shift A');
    } else if(test_key('B')){
        alert('Control Shift B');
    } else if(test_key('C')){
        alert('Control Shift C');
    }
}

(end of edit)


This example checks for CtrlShiftA, CtrlShiftB, and CtrlShiftC

It's just as simple as that :)

Notes

Keeping Track of KeyCodes

As a general rule, it is good practice to document code, especially things like Key codes (like // CTRL+ENTER) so you can remember what they were.

You should also put the key codes in the same order as the documentation (CTRL+ENTER => map[17] && map[13], NOT map[13] && map[17]). This way you won't ever get confused when you need to go back and edit the code.

A gotcha with if-else chains

If checking for combos of differing amounts (like CtrlShiftAltEnter and CtrlEnter), put smaller combos after larger combos, or else the smaller combos will override the larger combos if they are similar enough. Example:

// Correct:
if(map[17] && map[16] && map[13]){ // CTRL+SHIFT+ENTER
    alert('Whoa, mr. power user');
}else if(map[17] && map[13]){ // CTRL+ENTER
    alert('You found me');
}else if(map[13]){ // ENTER
    alert('You pressed Enter. You win the prize!')
}

// Incorrect:
if(map[17] && map[13]){ // CTRL+ENTER
    alert('You found me');
}else if(map[17] && map[16] && map[13]){ // CTRL+SHIFT+ENTER
    alert('Whoa, mr. power user');
}else if(map[13]){ // ENTER
    alert('You pressed Enter. You win the prize!');
}
// What will go wrong: When trying to do CTRL+SHIFT+ENTER, it will
// detect CTRL+ENTER first, and override CTRL+SHIFT+ENTER.
// Removing the else's is not a proper solution, either
// as it will cause it to alert BOTH "Mr. Power user" AND "You Found Me"

Gotcha: "This key combo keeps activating even though I'm not pressing the keys"

When dealing with alerts or anything that takes focus from the main window, you might want to include map = [] to reset the array after the condition is done. This is because some things, like alert(), take the focus away from the main window and cause the 'keyup' event to not trigger. For example:

if(map[17] && map[13]){ // CTRL+ENTER
    alert('Oh noes, a bug!');
}
// When you Press any key after executing this, it will alert again, even though you 
// are clearly NOT pressing CTRL+ENTER
// The fix would look like this:

if(map[17] && map[13]){ // CTRL+ENTER
    alert('Take that, bug!');
    map = {};
}
// The bug no longer happens since the array is cleared

Gotcha: Browser Defaults

Here's an annoying thing I found, with the solution included:

Problem: Since the browser usually has default actions on key combos (like CtrlD activates the bookmark window, or CtrlShiftC activates skynote on maxthon), you might also want to add return false after map = [], so users of your site won't get frustrated when the "Duplicate File" function, being put on CtrlD, bookmarks the page instead.

if(map[17] && map[68]){ // CTRL+D
    alert('The bookmark window didn\'t pop up!');
    map = {};
    return false;
}

Without return false, the Bookmark window would pop up, to the dismay of the user.

The return statement (new)

Okay, so you don't always want to exit the function at that point. That's why the event.preventDefault() function is there. What it does is set an internal flag that tells the interpreter to not allow the browser to run its default action. After that, execution of the function continues (whereas return will immediately exit the function).

Understand this distinction before you decide whether to use return false or e.preventDefault()

event.keyCode is deprecated

User SeanVieira pointed out in the comments that event.keyCode is deprecated.

There, he gave an excellent alternative: event.key, which returns a string representation of the key being pressed, like "a" for A, or "Shift" for Shift.

I went ahead and cooked up a tool for examining said strings.

element.onevent vs element.addEventListener

Handlers registered with addEventListener can be stacked, and are called in the order of registration, while setting .onevent directly is rather aggressive and overrides anything you previously had.

document.body.onkeydown = function(ev){
    // do some stuff
    ev.preventDefault(); // cancels default actions
    return false; // cancels this function as well as default actions
}

document.body.addEventListener("keydown", function(ev){
    // do some stuff
    ev.preventDefault() // cancels default actions
    return false; // cancels this function only
});

The .onevent property seems to override everything and the behavior of ev.preventDefault() and return false; can be rather unpredictable.

In either case, handlers registered via addEventlistener seem to be easier to write and reason about.

There is also attachEvent("onevent", callback) from Internet Explorer's non-standard implementation, but this is beyond deprecated and doesn't even pertain to JavaScript (it pertains to an esoteric language called JScript). It would be in your best interest to avoid polyglot code as much as possible.

A helper class

To address confusion/complaints, I've written a "class" that does this abstraction (pastebin link):

function Input(el){
    var parent = el,
        map = {},
        intervals = {};
    
    function ev_kdown(ev)
    {
        map[ev.key] = true;
        ev.preventDefault();
        return;
    }
    
    function ev_kup(ev)
    {
        map[ev.key] = false;
        ev.preventDefault();
        return;
    }
    
    function key_down(key)
    {
        return map[key];
    }

    function keys_down_array(array)
    {
        for(var i = 0; i < array.length; i++)
            if(!key_down(array[i]))
                return false;

        return true;
    }
    
    function keys_down_arguments()
    {
        return keys_down_array(Array.from(arguments));
    }
    
    function clear()
    {
        map = {};
    }
    
    function watch_loop(keylist, callback)
    {
        return function(){
            if(keys_down_array(keylist))
                callback();
        }
    }

    function watch(name, callback)
    {
        var keylist = Array.from(arguments).splice(2);

        intervals[name] = setInterval(watch_loop(keylist, callback), 1000/24);
    }

    function unwatch(name)
    {
        clearInterval(intervals[name]);
        delete intervals[name];
    }

    function detach()
    {
        parent.removeEventListener("keydown", ev_kdown);
        parent.removeEventListener("keyup", ev_kup);
    }
    
    function attach()
    {
        parent.addEventListener("keydown", ev_kdown);
        parent.addEventListener("keyup", ev_kup);
    }
    
    function Input()
    {
        attach();

        return {
            key_down: key_down,
            keys_down: keys_down_arguments,
            watch: watch,
            unwatch: unwatch,
            clear: clear,
            detach: detach
        };
    }
    
    return Input();
}

This class doesn't do everything and it won't handle every conceivable use case. I'm not a library guy. But for general interactive use it should be fine.

To use this class, create an instance and point it to the element you want to associate keyboard input with:

var input_txt = Input(document.getElementById("txt"));

input_txt.watch("print_5", function(){
    txt.value += "FIVE ";
}, "Control", "5");

What this will do is attach a new input listener to the element with #txt (let's assume it's a textarea), and set a watchpoint for the key combo Ctrl+5. When both Ctrl and 5 are down, the callback function you passed in (in this case, a function that adds "FIVE " to the textarea) will be called. The callback is associated with the name print_5, so to remove it, you simply use:

input_txt.unwatch("print_5");

To detach input_txt from the txt element:

input_txt.detach();

This way, garbage collection can pick up the object (input_txt), should it be thrown away, and you won't have an old zombie event listener left over.

For thoroughness, here is a quick reference to the class's API, presented in C/Java style so you know what they return and what arguments they expect.

Boolean  key_down (String key);

Returns true if key is down, false otherwise.

Boolean  keys_down (String key1, String key2, ...);

Returns true if all keys key1 .. keyN are down, false otherwise.

void     watch (String name, Function callback, String key1, String key2, ...);

Creates a "watchpoint" such that pressing all of keyN will trigger the callback

void     unwatch (String name);

Removes said watchpoint via its name

void     clear (void);

Wipes the "keys down" cache. Equivalent to map = {} above

void     detach (void);

Detaches the ev_kdown and ev_kup listeners from the parent element, making it possible to safely get rid of the instance

Update 2017-12-02 In response to a request to publish this to github, I have created a gist.

Update 2018-07-21 I've been playing with declarative style programming for a while, and this way is now my personal favorite: fiddle, pastebin

Generally, it'll work with the cases you would realistically want (ctrl, alt, shift), but if you need to hit, say, a+w at the same time, it wouldn't be too difficult to "combine" the approaches into a multi-key-lookup.


I hope this thoroughly explained answer mini-blog was helpful :)

望喜 2024-10-27 13:58:36
document.onkeydown = keydown; 

function keydown (evt) { 

    if (!evt) evt = event; 

    if (evt.ctrlKey && evt.altKey && evt.keyCode === 115) {

        alert("CTRL+ALT+F4"); 

    } else if (evt.shiftKey && evt.keyCode === 9) { 

        alert("Shift+TAB");

    } 

}
document.onkeydown = keydown; 

function keydown (evt) { 

    if (!evt) evt = event; 

    if (evt.ctrlKey && evt.altKey && evt.keyCode === 115) {

        alert("CTRL+ALT+F4"); 

    } else if (evt.shiftKey && evt.keyCode === 9) { 

        alert("Shift+TAB");

    } 

}
提笔落墨 2024-10-27 13:58:36

您应该使用 keydown 事件来跟踪按下的按键,您应该使用 keyup 事件来跟踪按下按键的时间。释放。

请参阅此示例: http://jsfiddle.net/vor0nwe/mkHsU/

(更新:我在此处复制代码,万一 jsfiddle.net 保释:)
HTML:

<ul id="log">
    <li>List of keys:</li>
</ul>

...和 ​​Javascript(使用 jQuery):

var log = $('#log')[0],
    pressedKeys = [];

$(document.body).keydown(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
        li = log.appendChild(document.createElement('li'));
        pressedKeys[evt.keyCode] = li;
    }
    $(li).text('Down: ' + evt.keyCode);
    $(li).removeClass('key-up');
});

$(document.body).keyup(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
       li = log.appendChild(document.createElement('li'));
    }
    $(li).text('Up: ' + evt.keyCode);
    $(li).addClass('key-up');
});

在该示例中,我使用一个数组来跟踪按下的键。在真实的应用程序中,您可能希望在释放每个元素的关联键后删除每个元素。

请注意,虽然在本例中我使用 jQuery 来让事情变得简单,但这个概念在“原始”Javascript 中工作时也同样有效。

You should use the keydown event to keep track of the keys pressed, and you should use the keyup event to keep track of when the keys are released.

See this example: http://jsfiddle.net/vor0nwe/mkHsU/

(Update: I’m reproducing the code here, in case jsfiddle.net bails:)
The HTML:

<ul id="log">
    <li>List of keys:</li>
</ul>

...and the Javascript (using jQuery):

var log = $('#log')[0],
    pressedKeys = [];

$(document.body).keydown(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
        li = log.appendChild(document.createElement('li'));
        pressedKeys[evt.keyCode] = li;
    }
    $(li).text('Down: ' + evt.keyCode);
    $(li).removeClass('key-up');
});

$(document.body).keyup(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
       li = log.appendChild(document.createElement('li'));
    }
    $(li).text('Up: ' + evt.keyCode);
    $(li).addClass('key-up');
});

In that example, I’m using an array to keep track of which keys are being pressed. In a real application, you might want to delete each element once their associated key has been released.

Note that while I've used jQuery to make things easy for myself in this example, the concept works just as well when working in 'raw' Javascript.

一袭水袖舞倾城 2024-10-27 13:58:36

对于需要完整示例代码的人。添加右+左

var keyPressed = {};
document.addEventListener('keydown', function(e) {

   keyPressed[e.key + e.location] = true;

    if(keyPressed.Shift1 == true && keyPressed.Control1 == true){
        // Left shift+CONTROL pressed!
        keyPressed = {}; // reset key map
    }
    if(keyPressed.Shift2 == true && keyPressed.Control2 == true){
        // Right shift+CONTROL pressed!
        keyPressed = {};
    }

}, false);

document.addEventListener('keyup', function(e) {
   keyPressed[e.key + e.location] = false;

   keyPressed = {};
}, false);

for who needs complete example code. Right+Left added

var keyPressed = {};
document.addEventListener('keydown', function(e) {

   keyPressed[e.key + e.location] = true;

    if(keyPressed.Shift1 == true && keyPressed.Control1 == true){
        // Left shift+CONTROL pressed!
        keyPressed = {}; // reset key map
    }
    if(keyPressed.Shift2 == true && keyPressed.Control2 == true){
        // Right shift+CONTROL pressed!
        keyPressed = {};
    }

}, false);

document.addEventListener('keyup', function(e) {
   keyPressed[e.key + e.location] = false;

   keyPressed = {};
}, false);
丘比特射中我 2024-10-27 13:58:36

这不是通用方法,但在某些情况下很有用。它对于 CTRL + somethingShift + somethingCTRL + 等组合很有用Shift + something 等。

示例:当您想使用 CTRL + P 打印页面时,第一个键按下的总是 CTRL 后跟 P。与 CTRL + SCTRL + U 和其他组合相同。

document.addEventListener('keydown',function(e){
      
    //SHIFT + something
    if(e.shiftKey){
        switch(e.code){

            case 'KeyS':
                console.log('Shift + S');
                break;

        }
    }

    //CTRL + SHIFT + something
    if(e.ctrlKey && e.shiftKey){
        switch(e.code){

            case 'KeyS':
                console.log('CTRL + Shift + S');
                break;

        }
    }

});

This is not a universal method, but it's usefull in some cases. It's usefull for combinations like CTRL + something or Shift + something or CTRL + Shift + something, etc.

Example: When you want to print a page using CTRL + P, first key pressed is always CTRL followed by P. Same with CTRL + S, CTRL + U and other combinations.

document.addEventListener('keydown',function(e){
      
    //SHIFT + something
    if(e.shiftKey){
        switch(e.code){

            case 'KeyS':
                console.log('Shift + S');
                break;

        }
    }

    //CTRL + SHIFT + something
    if(e.ctrlKey && e.shiftKey){
        switch(e.code){

            case 'KeyS':
                console.log('CTRL + Shift + S');
                break;

        }
    }

});

冰之心 2024-10-27 13:58:36

我用这种方式(必须检查 Shift + Ctrl 按下的位置):

// create some object to save all pressed keys
var keys = {
    shift: false,
    ctrl: false
};

$(document.body).keydown(function(event) {
// save status of the button 'pressed' == 'true'
    if (event.keyCode == 16) {
        keys["shift"] = true;
    } else if (event.keyCode == 17) {
        keys["ctrl"] = true;
    }
    if (keys["shift"] && keys["ctrl"]) {
        $("#convert").trigger("click"); // or do anything else
    }
});

$(document.body).keyup(function(event) {
    // reset status of the button 'released' == 'false'
    if (event.keyCode == 16) {
        keys["shift"] = false;
    } else if (event.keyCode == 17) {
        keys["ctrl"] = false;
    }
});

I used this way (had to check wherever is Shift + Ctrl pressed):

// create some object to save all pressed keys
var keys = {
    shift: false,
    ctrl: false
};

$(document.body).keydown(function(event) {
// save status of the button 'pressed' == 'true'
    if (event.keyCode == 16) {
        keys["shift"] = true;
    } else if (event.keyCode == 17) {
        keys["ctrl"] = true;
    }
    if (keys["shift"] && keys["ctrl"]) {
        $("#convert").trigger("click"); // or do anything else
    }
});

$(document.body).keyup(function(event) {
    // reset status of the button 'released' == 'false'
    if (event.keyCode == 16) {
        keys["shift"] = false;
    } else if (event.keyCode == 17) {
        keys["ctrl"] = false;
    }
});
偏爱你一生 2024-10-27 13:58:36

我喜欢使用这个片段,它对于编写游戏输入脚本非常有用

var keyMap = [];

window.addEventListener('keydown', (e)=>{
    if(!keyMap.includes(e.keyCode)){
        keyMap.push(e.keyCode);
    }
})

window.addEventListener('keyup', (e)=>{
    if(keyMap.includes(e.keyCode)){
        keyMap.splice(keyMap.indexOf(e.keyCode), 1);
    }
})

function key(x){
    return (keyMap.includes(x));
}

function checkGameKeys(){
    if(key(32)){
        // Space Key
    }
    if(key(37)){
        // Left Arrow Key
    }
    if(key(39)){
        // Right Arrow Key
    }
    if(key(38)){
        // Up Arrow Key
    }
    if(key(40)){
        // Down Arrow Key
    }
    if(key(65)){
        // A Key
    }
    if(key(68)){
        // D Key
    }
    if(key(87)){
        // W Key
    }
    if(key(83)){
        // S Key
    }
}

I like to use this snippet, its very useful for writing game input scripts

var keyMap = [];

window.addEventListener('keydown', (e)=>{
    if(!keyMap.includes(e.keyCode)){
        keyMap.push(e.keyCode);
    }
})

window.addEventListener('keyup', (e)=>{
    if(keyMap.includes(e.keyCode)){
        keyMap.splice(keyMap.indexOf(e.keyCode), 1);
    }
})

function key(x){
    return (keyMap.includes(x));
}

function checkGameKeys(){
    if(key(32)){
        // Space Key
    }
    if(key(37)){
        // Left Arrow Key
    }
    if(key(39)){
        // Right Arrow Key
    }
    if(key(38)){
        // Up Arrow Key
    }
    if(key(40)){
        // Down Arrow Key
    }
    if(key(65)){
        // A Key
    }
    if(key(68)){
        // D Key
    }
    if(key(87)){
        // W Key
    }
    if(key(83)){
        // S Key
    }
}
┼── 2024-10-27 13:58:36

这是 Bradens 答案的实现。

var keys = {}
function handleKeyPress(evt) {
  let { keyCode, type } = evt || Event; // to deal with IE
  let isKeyDown = (type == 'keydown');
  keys[keyCode] = isKeyDown;

  // test: enter key is pressed down & shift isn't currently being pressed down 
  if(isKeyDown && keys[13] && !keys[16]){
    console.log('user pressed enter without shift')
  }
};

window.addEventListener("keyup", handleKeyPress);
window.addEventListener("keydown", handleKeyPress);

Here's an implementation of Bradens answer.

var keys = {}
function handleKeyPress(evt) {
  let { keyCode, type } = evt || Event; // to deal with IE
  let isKeyDown = (type == 'keydown');
  keys[keyCode] = isKeyDown;

  // test: enter key is pressed down & shift isn't currently being pressed down 
  if(isKeyDown && keys[13] && !keys[16]){
    console.log('user pressed enter without shift')
  }
};

window.addEventListener("keyup", handleKeyPress);
window.addEventListener("keydown", handleKeyPress);

知足的幸福 2024-10-27 13:58:36

使按键甚至调用多个函数,每个函数检查特定的键并做出适当的响应。

document.keydown = function (key) {

    checkKey("x");
    checkKey("y");
};

Make the keydown even call multiple functions, with each function checking for a specific key and responding appropriately.

document.keydown = function (key) {

    checkKey("x");
    checkKey("y");
};
瑶笙 2024-10-27 13:58:36
    $(document).ready(function () {
        // using ascii 17 for ctrl, 18 for alt and 83 for "S"
        // ctr+alt+S
        var map = { 17: false, 18: false, 83: false };
        $(document).keyup(function (e) {
            if (e.keyCode in map) {
                map[e.keyCode] = true;
                if (map[17] && map[18] && map[83]) {
                    // Write your own code here, what  you want to do
                    map[17] = false;
                    map[18] = false;
                    map[83] = false;
                }
            }
            else {
                // if u press any other key apart from that "map" will reset.
                map[17] = false;
                map[18] = false;
                map[83] = false;
            }
        });

    });
    $(document).ready(function () {
        // using ascii 17 for ctrl, 18 for alt and 83 for "S"
        // ctr+alt+S
        var map = { 17: false, 18: false, 83: false };
        $(document).keyup(function (e) {
            if (e.keyCode in map) {
                map[e.keyCode] = true;
                if (map[17] && map[18] && map[83]) {
                    // Write your own code here, what  you want to do
                    map[17] = false;
                    map[18] = false;
                    map[83] = false;
                }
            }
            else {
                // if u press any other key apart from that "map" will reset.
                map[17] = false;
                map[18] = false;
                map[83] = false;
            }
        });

    });
闻呓 2024-10-27 13:58:36

我会尝试在 keydown 上添加一个 keypress Event 处理程序。例如:

window.onkeydown = function() {
    // evaluate key and call respective handler
    window.onkeypress = function() {
       // evaluate key and call respective handler
    }
}

window.onkeyup = function() {
    window.onkeypress = void(0) ;
}

这只是为了说明一种模式;我不会在这里详细介绍(特别是不涉及浏览器特定的 level2+ Event 注册)。

请回帖无论这是否有帮助。

I'd try adding a keypress Event handler upon keydown. E.g:

window.onkeydown = function() {
    // evaluate key and call respective handler
    window.onkeypress = function() {
       // evaluate key and call respective handler
    }
}

window.onkeyup = function() {
    window.onkeypress = void(0) ;
}

This is just meant to illustrate a pattern; I won't go into detail here (especially not into browser specific level2+ Event registration).

Post back please whether this helps or not.

勿忘初心 2024-10-27 13:58:36

如果按下的键之一是 Alt / Crtl / Shift 您可以使用此方法:

document.body.addEventListener('keydown', keysDown(actions) );

function actions() {
   // do stuff here
}

// simultaneous pressing Alt + R
function keysDown (cb) {
  return function (zEvent) {
    if (zEvent.altKey &&  zEvent.code === "KeyR" ) {
      return cb()
    }
  }
}

If one of keys pressed is Alt / Crtl / Shift you can use this method:

document.body.addEventListener('keydown', keysDown(actions) );

function actions() {
   // do stuff here
}

// simultaneous pressing Alt + R
function keysDown (cb) {
  return function (zEvent) {
    if (zEvent.altKey &&  zEvent.code === "KeyR" ) {
      return cb()
    }
  }
}
做个少女永远怀春 2024-10-27 13:58:36

如果有人需要简单的解决方案。

let keys = [];
document.addEventListener("keydown", (e) => {
  keys.push(e.key);
  if (keys.includes("Control") && keys.includes("o")) {
    console.log("open");
  }

  if (keys.includes("Control") && keys.includes("s")) {
    console.log("save");
  }
});

// clear the keys array
document.addEventListener("keyup", () => {
  keys = [];
});

If someone needs easy solution.

let keys = [];
document.addEventListener("keydown", (e) => {
  keys.push(e.key);
  if (keys.includes("Control") && keys.includes("o")) {
    console.log("open");
  }

  if (keys.includes("Control") && keys.includes("s")) {
    console.log("save");
  }
});

// clear the keys array
document.addEventListener("keyup", () => {
  keys = [];
});
你又不是我 2024-10-27 13:58:36
case 65: //A
jp = 1;
setTimeout("jp = 0;", 100);

if(pj > 0) {
ABFunction();
pj = 0;
}
break;

case 66: //B
pj = 1;
setTimeout("pj = 0;", 100);

if(jp > 0) {
ABFunction();
jp = 0;
}
break;

我知道这不是最好的方法。

case 65: //A
jp = 1;
setTimeout("jp = 0;", 100);

if(pj > 0) {
ABFunction();
pj = 0;
}
break;

case 66: //B
pj = 1;
setTimeout("pj = 0;", 100);

if(jp > 0) {
ABFunction();
jp = 0;
}
break;

Not the best way, I know.

烟若柳尘 2024-10-27 13:58:36

如果你想找到任何带有控制键的按键事件,你可以这样做

onkeypress = (e) =>{
console.log(e);
if(e.ctrlKey && e.code == "KeyZ"){
    document.write("do somthing")
} }

if you want to find any keypress event with control key you can do like this

onkeypress = (e) =>{
console.log(e);
if(e.ctrlKey && e.code == "KeyZ"){
    document.write("do somthing")
} }
最美不过初阳 2024-10-27 13:58:36

只是让东西更稳定:

var keys = [];
$(document).keydown(function (e) { 
    if(e.which == 32 || e.which == 70){
    keys.push(e.which);
    if(keys.length == 2 && keys.indexOf(32) != -1 && keys.indexOf(70) != -1){
        
        
        
        alert("it WORKS !!"); //MAKE SOMETHING HERE---------------->
        
        
        
        keys.length = 0;
    }else if((keys.indexOf(32) == -1 && keys.indexOf(70) != -1) || (keys.indexOf(32) != -1 && keys.indexOf(70) == -1) && (keys.indexOf(32) > 1 || keys.indexOf(70) > 1)){
    }else{
        keys.length = 0;
    }
}else{
    keys.length = 0;
}
});

Just making something more stable :

var keys = [];
$(document).keydown(function (e) { 
    if(e.which == 32 || e.which == 70){
    keys.push(e.which);
    if(keys.length == 2 && keys.indexOf(32) != -1 && keys.indexOf(70) != -1){
        
        
        
        alert("it WORKS !!"); //MAKE SOMETHING HERE---------------->
        
        
        
        keys.length = 0;
    }else if((keys.indexOf(32) == -1 && keys.indexOf(70) != -1) || (keys.indexOf(32) != -1 && keys.indexOf(70) == -1) && (keys.indexOf(32) > 1 || keys.indexOf(70) > 1)){
    }else{
        keys.length = 0;
    }
}else{
    keys.length = 0;
}
});
ぶ宁プ宁ぶ 2024-10-27 13:58:36

对于使用 React 的用户,这是我的解决方案:

import { useEffect, useState } from "react";
import Backdrop from '@mui/material/Backdrop';

export const Example = () => {
  const [backdropOpen, setBackdropOpen] = useState(false);

  useEffect(() => {
    // Keys that need to be pressed at the same time in order for
    // the 'backdropOpen' variable to be 'true'
    const keysArr = ['ControlLeft', 'ShiftLeft', 'AltLeft'];
    const keysMap = {};
    let backdropOpenLocal = false;

    const keydownEvent = 'keydown';
    const keyupEvent = 'keyup';

    const checkKeys = () => {
      const keysArePressed = keysArr.every((value) => keysMap[value] === keydownEvent);
      if (keysArePressed !== backdropOpenLocal) {
        backdropOpenLocal = keysArePressed;
        setBackdropOpen(keysArePressed);
      }
    }

    const handleKeyDown = (event) => {
      const keyCode = event.code;
      if (keysArr.includes(keyCode) && keysMap[keyCode] !== keydownEvent) {
        keysMap[keyCode] = keydownEvent;
      }
      checkKeys();
    }

    const handleKeyUp = (event) => {
      const keyCode = event.code;
      if (keysArr.includes(keyCode) && keysMap[keyCode] !== keyupEvent) {
        keysMap[keyCode] = keyupEvent;
      }
      checkKeys();
    }

    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);

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

  return (
    <React.Fragmemnt>
      <div>
        <Backdrop
          open={backdropOpen}
        >
          <span>
            It worked!
          </span>
        </Backdrop>
      </div>
    </React.Fragmemnt>
  );
}

请记住,我们需要在 useEffect 函数中使用 backdropOpenLocal 而不是 backdropOpen,因为我们只想更新局部作用域变量并保留作用域的状态。

如果我们更新Example组件的状态并尝试访问backdropOpen,我们将获得与之前相同的值,除非我们在<的依赖项数组中传入backdropOpen代码>useEffect;这将导致 useEffect 内的作用域变量被重置,而我们不希望出现这种情况。

For whoever is using React, here is my solution:

import { useEffect, useState } from "react";
import Backdrop from '@mui/material/Backdrop';

export const Example = () => {
  const [backdropOpen, setBackdropOpen] = useState(false);

  useEffect(() => {
    // Keys that need to be pressed at the same time in order for
    // the 'backdropOpen' variable to be 'true'
    const keysArr = ['ControlLeft', 'ShiftLeft', 'AltLeft'];
    const keysMap = {};
    let backdropOpenLocal = false;

    const keydownEvent = 'keydown';
    const keyupEvent = 'keyup';

    const checkKeys = () => {
      const keysArePressed = keysArr.every((value) => keysMap[value] === keydownEvent);
      if (keysArePressed !== backdropOpenLocal) {
        backdropOpenLocal = keysArePressed;
        setBackdropOpen(keysArePressed);
      }
    }

    const handleKeyDown = (event) => {
      const keyCode = event.code;
      if (keysArr.includes(keyCode) && keysMap[keyCode] !== keydownEvent) {
        keysMap[keyCode] = keydownEvent;
      }
      checkKeys();
    }

    const handleKeyUp = (event) => {
      const keyCode = event.code;
      if (keysArr.includes(keyCode) && keysMap[keyCode] !== keyupEvent) {
        keysMap[keyCode] = keyupEvent;
      }
      checkKeys();
    }

    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);

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

  return (
    <React.Fragmemnt>
      <div>
        <Backdrop
          open={backdropOpen}
        >
          <span>
            It worked!
          </span>
        </Backdrop>
      </div>
    </React.Fragmemnt>
  );
}

Keep in mind that we need to use the backdropOpenLocal instead of backdropOpen inside the useEffect function, because we want to update the local scoped variable only and keep the state of the scope.

If we update the state of the Example component and try to access backdropOpen, we will have the same value as before, unless we pass in the backdropOpen in the dependency array of useEffect; this would cause the scoped variables inside useEffect to be reset, and we don't want that.

终难愈 2024-10-27 13:58:36

我使用案例、if 和 bool。我有一个项目,这对我来说非常有用


window.addEventListener("keydown", onKeyDown, false);
window.addEventListener("keyup", onKeyUp, false);

function onKeyDown(event) {
  var keyCode = event.keyCode;
  switch (keyCode) {
    case 68: //D
      keyd = true;
      break;
    case 32: //spaaaaaaaaaaaaaaace
      keyspace = true;
      break;
    case 65: //A
      keya = true;
      break;
    case 37:
      keya = true;
      break;
    case 38:
      keyspace = true;
      break;
    case 39:
      keyd = true;
      break;
  }
}

function onKeyUp(event) {
  var keyCode = event.keyCode;

  switch (keyCode) {
    case 68: //dddddd
      keyd = false;
      break;
    case 32: //spaaaaaaaaaaaaaaaaaaaaaace
      keyspace = false;
      break;
    case 65: //aaaaa
      keya = false;
      break;
    case 37:
      keya = false;
      break;
    case 38:
      keyspace = false;
      break;
    case 39:
      keyd = false;
      break;
  }
}

||更新||

我制作了一个包含关键变量的库,这里是如何使用它:

Key['key']

这是一个例子:

function loop(){
    if(Key['w']){
        console.log("w was pressed");
    }
}

setInterval(loop,1);

就是这样,你可以将它放在你的项目中,有点像jquery,这也需要jquery,这里是:

<script src="posh.glitch.me/libraries/library.js"></script>

i use cases, ifs and bools. I had a project and this worked great for me


window.addEventListener("keydown", onKeyDown, false);
window.addEventListener("keyup", onKeyUp, false);

function onKeyDown(event) {
  var keyCode = event.keyCode;
  switch (keyCode) {
    case 68: //D
      keyd = true;
      break;
    case 32: //spaaaaaaaaaaaaaaace
      keyspace = true;
      break;
    case 65: //A
      keya = true;
      break;
    case 37:
      keya = true;
      break;
    case 38:
      keyspace = true;
      break;
    case 39:
      keyd = true;
      break;
  }
}

function onKeyUp(event) {
  var keyCode = event.keyCode;

  switch (keyCode) {
    case 68: //dddddd
      keyd = false;
      break;
    case 32: //spaaaaaaaaaaaaaaaaaaaaaace
      keyspace = false;
      break;
    case 65: //aaaaa
      keya = false;
      break;
    case 37:
      keya = false;
      break;
    case 38:
      keyspace = false;
      break;
    case 39:
      keyd = false;
      break;
  }
}

||UPDATE||

I made a library that includes a key variable, here is how to use it:

Key['key']

and here is an example:

function loop(){
    if(Key['w']){
        console.log("w was pressed");
    }
}

setInterval(loop,1);

that's it, you can put it inside of your projects kinda like jquery, this also needs jquery, here it is:

<script src="posh.glitch.me/libraries/library.js"></script>
南风几经秋 2024-10-27 13:58:36

您可以使用 keydown 添加它们的键并删除它们或在 keyup 上将它们设置为 false :

var keys = {};
 window.addEventListener("keydown", function(e) {
    if (e.key == 'w') { keys[e.key] = true; }
    if (e.key == 's') { keys[e.key] = true; }
    if (e.key == 'a') { keys[e.key] = true; }
    if (e.key == 'd') { keys[e.key] = true; }
  });
  window.addEventListener("keyup", function(e) {
    if (e.key == 'w') { keys[e.key] = false; }
    if (e.key == 's') { keys[e.key] = false; }
    if (e.key == 'a') { keys[e.key] = false; }
    if (e.key == 'd') { keys[e.key] = false; }
  });

您可以这样检查:

  if (keys['w'] && keys['d']) {
    console.log("oook");
  }

每当您执行 keyup 时,它都会将其设置为 false 。

You Can Add They Keys using keydown and remove them or set them to false on keyup :

var keys = {};
 window.addEventListener("keydown", function(e) {
    if (e.key == 'w') { keys[e.key] = true; }
    if (e.key == 's') { keys[e.key] = true; }
    if (e.key == 'a') { keys[e.key] = true; }
    if (e.key == 'd') { keys[e.key] = true; }
  });
  window.addEventListener("keyup", function(e) {
    if (e.key == 'w') { keys[e.key] = false; }
    if (e.key == 's') { keys[e.key] = false; }
    if (e.key == 'a') { keys[e.key] = false; }
    if (e.key == 'd') { keys[e.key] = false; }
  });

you can check like that:

  if (keys['w'] && keys['d']) {
    console.log("oook");
  }

and when ever you do keyup it will set it to false.

睡美人的小仙女 2024-10-27 13:58:36
Easiest, and most Effective Method

//check key press
    function loop(){
        //>>key<< can be any string representing a letter eg: "a", "b", "ctrl",
        if(map[*key*]==true){
         //do something
        }
        //multiple keys
        if(map["x"]==true&&map["ctrl"]==true){
         console.log("x, and ctrl are being held down together")
        }
    }

//>>>variable which will hold all key information<<
    var map={}

//Key Event Listeners
    window.addEventListener("keydown", btnd, true);
    window.addEventListener("keyup", btnu, true);

    //Handle button down
      function btnd(e) {
      map[e.key] = true;
      }

    //Handle Button up
      function btnu(e) {
      map[e.key] = false;
      }

//>>>If you want to see the state of every Key on the Keybaord<<<
    setInterval(() => {
                for (var x in map) {
                    log += "|" + x + "=" + map[x];
                }
                console.log(log);
                log = "";
            }, 300);
Easiest, and most Effective Method

//check key press
    function loop(){
        //>>key<< can be any string representing a letter eg: "a", "b", "ctrl",
        if(map[*key*]==true){
         //do something
        }
        //multiple keys
        if(map["x"]==true&&map["ctrl"]==true){
         console.log("x, and ctrl are being held down together")
        }
    }

//>>>variable which will hold all key information<<
    var map={}

//Key Event Listeners
    window.addEventListener("keydown", btnd, true);
    window.addEventListener("keyup", btnu, true);

    //Handle button down
      function btnd(e) {
      map[e.key] = true;
      }

    //Handle Button up
      function btnu(e) {
      map[e.key] = false;
      }

//>>>If you want to see the state of every Key on the Keybaord<<<
    setInterval(() => {
                for (var x in map) {
                    log += "|" + x + "=" + map[x];
                }
                console.log(log);
                log = "";
            }, 300);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文