jQuery 特定键的 keydown + keyup 事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16345870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 16:58:35  来源:igfitidea点击:

keydown + keyup events for specific keys

javascriptjquerykeypresskeydownkeyup

提问by Roko C. Buljan

I'm trying to make the background color change when certain keys are held down. For example, when the 'r' key is being held down, the background should be red. When the 'r' key is not being pressed anymore, the background should default to white.

我试图在按住某些键时更改背景颜色。例如,当“r”键被按住时,背景应该是红色的。当不再按下“r”键时,背景应默认为白色。

$(document).ready(function () {
    $('body').keydown(function(e){
        if(e.keyCode == 114){
            $(this).css({'background':'red'});  
        }
        if(e.keyCode == 121){
            $(this).css({'background':'yellow'});
        }
    });
    $('body').keypress(function(e){
        if(e.keyCode == 114){
            $(this).css({'background':'red'});  
        }
        if(e.keyCode == 121){
            $(this).css({'background':'yellow'});
        }
    });
    $('body').keyup(function(e){
        if(e.keyCode == 114){
            $(this).css({'background':'white'});
        }
        if(e.keyCode == 121){
            $(this).css({'background':'white'});
        }
    });

});

The problem I'm having is that keyup is not working specifically for each individual key.

我遇到的问题是 keyup 不是专门针对每个单独的键工作的。

    $('body').keyup(function(e){
        $(this).css({'background':'white'});
    });

I know if I remove the if conditionals from keyup altogether then it will behave how I said I wanted it to — but I want to be able to do different things later on using keyup with specific keys. For example, when just the 'b' key is released, maybe it will say something on the screen like "You just released the b key!" How can I keep track of keydown and keyup events for specific keys and make different things happen for each? I know this isn't very organized either (I'm pretty new to this stuff) so if there's a completely different and better way of doing this...

我知道如果我从 keyup 中完全删除 if 条件,那么它会按照我所说的那样运行——但是我希望以后能够在使用带有特定键的 keyup 时做不同的事情。例如,当仅释放 'b' 键时,它可能会在屏幕上显示诸如“您刚刚释放了 b 键!”之类的信息。如何跟踪特定键的 keydown 和 keyup 事件并为每个键发生不同的事情?我知道这也不是很有条理(我对这些东西很陌生)所以如果有一种完全不同和更好的方法来做到这一点......

回答by Roko C. Buljan

Handle Keyboard in JavaScript

在 JavaScript 中处理键盘

1. List of Action functions

1.动作功能一览

Create an Object literal list with your desired functions. Say you have a character you want to move, here are some example Actions:

使用您想要的函数创建一个对象文字列表。假设您有一个想要移动的角色,以下是一些示例Actions

const Action = {
  powerOn()  { console.log("Accelerating..."); },
  powerOff() { console.log("Decelerating..."); },
  brakeOn()  { console.log("Break activated"); },
  brakeOff() { console.log("Break released");  },
  exit()     { console.log("Nice drive!");     },
  // clutch, colors, lights, fire... Add more, go wild!
};

PS: In a real-case scenario every single function would contain the actual logic to handle the character, being it a one-time "move-by-N-px", or act as a proxy to populate a queue which is than consumed by a frame-rate engine like Window.requestAnimationFrame. You can also create functions to change colors, etc. You got the general idea.

PS:在实际情况下,每个函数都将包含处理角色的实际逻辑,无论是一次性“move-by-N-px”,还是充当代理填充队列,然后消耗通过像Window.requestAnimationFrame这样的帧率引擎。您还可以创建函数来更改颜色等。您已经大致了解了。

2. Associate Keys to Actions by Event.type

2. 通过 Event.type 将 Key 与 Actions 关联

Associate KeyboardEvent.key to the desired Action for a desired Event.type (←must be lowercase):

将 KeyboardEvent.key 与所需 Event.type 的所需操作关联(← 必须为小写):

const keyAction = {
  w:      { keydown: Action.powerOn,  keyup: Action.powerOff },
  s:      { keydown: Action.brakeOn,  keyup: Action.brakeOff },
  Escape: { keydown: Action.exit }
};

Notice that the key-names "w""s""Escape"are represented as the returned value of the preferredKeyboardEvent.key, instead of the numeric KeyboardEvent.keyCode. We're humans, not robots.

请注意,键名"w""s""Escape"表示为preferredKeyboardEvent.key的返回值,而不是数字KeyboardEvent.keyCode。我们是人,不是机器人。

3. KeyboardEvent handler

3. 键盘事件处理程序

Finally, let's listen to the "keyup""keydown"Events and trigger a callback function keyHandler, that will eventually trigger our specific Action function, say i.e: keyAction["w"]["keydown"]()which is actually our spaceship's powerOnAction function!

最后,让我们监听"keyup""keydown"事件并触发一个回调函数keyHandler,它最终会触发我们特定的 Action 函数,比如说:keyAction["w"]["keydown"]()这实际上是我们飞船的powerOnAction 函数!

const keyHandler = (ev) => {
  if (ev.repeat) return; // Key-held, prevent repeated Actions (Does not work in IE11-)
  if (!(ev.key in keyAction) || !(ev.type in keyAction[ev.key])) return; // No such Action
  keyAction[ev.key][ev.type]();  // Trigger an Action
};

['keydown', 'keyup'].forEach((evType) => {
    document.body.addEventListener(evType, keyHandler);
});

Result:

结果:

const Action = {
  powerOn()  { console.log("Accelerating..."); },
  powerOff() { console.log("Decelerating..."); },
  brakeOn()  { console.log("Break activated"); },
  brakeOff() { console.log("Break released");  },
  exit()     { console.log("Nice drive!");     },
};

const keyAction = {
  w: { keydown: Action.powerOn,  keyup: Action.powerOff },
  s: { keydown: Action.brakeOn,  keyup: Action.brakeOff },
  Escape: { keydown: Action.exit }
};

const keyHandler = (ev) => {
  if (ev.repeat) return;                             
  if (!(ev.key in keyAction) || !(ev.type in keyAction[ev.key])) return;
  keyAction[ev.key][ev.type]();
};

['keydown', 'keyup'].forEach((evType) => {
  document.body.addEventListener(evType, keyHandler);
});
Click here to fucus this window.<br>
Than, use [<kbd>W</kbd>], [<kbd>S</kbd>] or [<kbd>Esc</kbd>] keys on your keyboard.



Example for your specific request:

您的特定要求的示例:

const changeBG = (color) => document.body.style.background = color;

const Action = {
  red()    { changeBG("#f00"); },
  yellow() { changeBG("yellow"); },
  orange() { changeBG("orange"); },
  reset()  { changeBG(""); },
};

const keyAction = {
  r: { keydown: Action.red,    keyup: Action.reset },
  y: { keydown: Action.yellow, keyup: Action.reset },
  o: { keydown: Action.orange }, // No keyup for this one :)
};

const keyHandler = (ev) => {
  if (ev.repeat) return;  
  if (!(ev.key in keyAction) || !(ev.type in keyAction[ev.key])) return;
  keyAction[ev.key][ev.type]();
};

['keydown', 'keyup'].forEach((evType) => {
  document.body.addEventListener(evType, keyHandler);
});
body { transition: background: 0.3s; }
Click here to fucus this window. <br>Keys:<br>
[<kbd>Y</kbd>] for Yellow<br>
[<kbd>R</kbd>] for Red<br>
[<kbd>O</kbd>] to permanently set to Orange

回答by ilan berci



$().ready(function() {
  $('body').on("keyup keydown", function() {
    if(e.keyCode == 114 || e.keyCode = 121) {
      $(this).toggleClass("key" + e.keyCode)
    }
  })
})


Now just match the css rules with your css classes

现在只需将 css 规则与您的 css 类匹配