keydown + keyup events for specific keys

后端 未结 2 395
小蘑菇
小蘑菇 2020-12-14 04:22

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 \

2条回答
  •  醉梦人生
    2020-12-14 04:35

    Handle Keyboard in JavaScript

    1. List of Action functions

    Create an Object literal list with your desired functions. Say you have a character you want to move, here are some example 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.

    2. Associate Keys to Actions by Event.type

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

    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 preferred KeyboardEvent.key, instead of the numeric KeyboardEvent.keyCode. We're humans, not robots.

    3. KeyboardEvent handler

    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 powerOn Action function!

    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.
    Than, use [W], [S] or [Esc] 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. 
    Keys:
    [Y] for Yellow
    [R] for Red
    [O] to permanently set to Orange

提交回复
热议问题