特定按键的keydown和keyup事件

13

我试图在按下某些键时改变背景颜色。例如,当按住“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'});
        }
    });

});

我遇到的问题是,keyup事件不能针对每个按键单独工作。

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

我知道如果完全删除keyup中的if条件语句,那么它将按照我的意愿进行--但是我希望以后能够使用keyup来执行特定键的不同操作。例如,当释放'b'键时,也许屏幕上会显示"你刚刚释放了b键!" 如何跟踪特定键的keydown和keyup事件,并使每个键都执行不同的操作?我知道这样做也不是很有条理(我对这方面还很新),所以如果有完全不同且更好的方法...


你尝试过使用 e.which 替代 e.keyCode 吗?https://dev59.com/_3VC5IYBdhLWcg3wbQXA#302161 - uross
2个回答

20

处理JavaScript中的键盘

1. 动作函数列表

创建一个对象字面量列表,包括您所需的函数。例如,如果您想要移动角色,以下是一些示例动作

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:在实际情况下,每个函数都会包含处理字符的实际逻辑,无论是一次性的“移动N像素”,还是作为代理填充队列,然后由类似Window.requestAnimationFrame的帧率引擎消耗。您还可以创建函数来更改颜色等。你已经得到了大致的想法。

2. 通过事件类型将按键关联到操作

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

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

请注意,键名“w”、“s”和“Escape”被表示为首选的KeyboardEvent.key返回值,而不是数字KeyboardEvent.keyCode。我们是人类,不是机器人。

3. KeyboardEvent 处理程序

最后,让我们监听"keyup""keydown"事件,并触发回调函数keyHandler,该函数最终会触发我们特定的操作函数,例如:keyAction["w"]["keydown"](),这实际上是我们飞船的powerOn操作函数!
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);
});

结果:

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 focus this window.<br>
Then, use [<kbd>W</kbd>], [<kbd>S</kbd>] or [<kbd>Esc</kbd>] keys on your keyboard.


您的具体请求示例:

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 focus 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


假设我想在 b 键释放时显示一个隐藏的对象,并在释放不同键时使另一个对象移动 - 如何使用此方法实现?我想能够针对各个键的 keyup 和 keydown 进行不同的操作,而不仅仅是改变颜色。 - user1115666
我马上要去上班了,等我回家后一定会再来这里看你的新例子。再次感谢! - user1115666
1
太好了!如果我想在按键按下时向元素添加CSS类[.addClass()],并在按键抬起时删除该类[.removeClass()]或添加另一个类,我该怎么做?例如,如果我按下“z”键(90),它应该是这样的:90:['#div','addClass',"?",['addedclass?','removedclass?']] ??? - user1115666
@luke 我可以知道这是关于什么的吗?你想要实现什么具体的目标? - Roko C. Buljan
例如,当按下前进键时,将向角色添加“行走”类,并删除“空闲”类。背景也会获得“移动”类以开始向正确方向滚动。我可以继续使用所有不同的类来制作角色和环境,并说明如何模拟碰撞检测。 - user1115666
显示剩余6条评论

-1


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


现在只需将 CSS 规则与您的 CSS 类匹配即可


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接