Asension
Asension

Reputation: 95

How to detect if multiple keys are being pressed at the same time in html using JavaScript

I am currently working on a keyboard recognition project and creating a simple game in order to demonstrate my understanding of it. When I press the four keys: W, S, A, D, it will print out the direction corresponding to them. (ex. W = Up). A demo down below:

var msg = new SpeechSynthesisUtterance();
var synth = window.speechSynthesis;

function uniKeyCode(event) {
    var key = event.which || event.keyCode;
    // console.log(key)
    if (key == 32 || key == 13) {
        document.getElementById("actionCenter").innerHTML = "fire"
        msg = new SpeechSynthesisUtterance("fire");

        //settings
        msg.rate = 1.2; //speech speed - range: 0 to 10
        //look into console to see all available voices/languages
        msg.voice = synth.getVoices()[0];

        //speaking trigger
        synth.cancel(); //cut previous voice short
        synth.speak(msg);
    }

    if (key == 87 || key == 38) {
        document.getElementById("actionCenter").innerHTML = "jump"
        msg = new SpeechSynthesisUtterance("jump");

        msg.rate = 1.2;
        msg.voice = synth.getVoices()[0];

        synth.cancel();
        synth.speak(msg);
    }

    if (key == 83 || key == 40) {
        document.getElementById("actionCenter").innerHTML = "roll"
        msg = new SpeechSynthesisUtterance("roll");

        msg.rate = 1.2;
        msg.voice = synth.getVoices()[0];

        synth.cancel();
        synth.speak(msg);
    }

    if (key == 65 || key == 37) {
        document.getElementById("actionCenter").innerHTML = "roll left"
        msg = new SpeechSynthesisUtterance("roll left");

        msg.rate = 1.2;
        msg.voice = synth.getVoices()[0];

        synth.cancel();
        synth.speak(msg);
    }

    if (key == 68 || key == 39) {
        document.getElementById("actionCenter").innerHTML = "roll right"
        msg = new SpeechSynthesisUtterance("roll right");

        msg.rate = 1.2;
        msg.voice = synth.getVoices()[0];

        synth.cancel();
        synth.speak(msg);
    }
}
.center {
    text-align: center;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
    <title>Assignment 11a2</title>
</head>

<body onkeydown="uniKeyCode(event)">
    <p class="center">Actions
        <br>
        <span id="actionCenter"></span></p>
    <script src="11a2.js"></script>
</body>

</html>

Right now I am trying to make an action for when multiple keys are pressed at the same time(ex. W + A = Jump Left). I tried this:

if (key == 87 && key == 65) {
   document.getElementById ("actionCenter").innerHTML = "Jump Left"
}

but apparently, it did not work. The code runs as if those three lines do not exist. What is the problem?

Upvotes: 1

Views: 7017

Answers (5)

rarksoca
rarksoca

Reputation: 98

Spankied's answer work well with console log but this will stop working correctly once press a key, change browser tab, release key, and then get back to your application tab. Your code will still “think” that which is already release, is still pressed. Or if you change console.log to alert then it will work first time but stop working after alert. If clear keys keys = {}; after alert then it work well (for me)

var keys = {};
window.addEventListener('keydown', (e) => {
  keys[e.key] = true;
  if (keys['1'] && keys['2']) {
    alert('1 + 2');
    keys = {}; // add this will work well
  }
});

window.addEventListener('keyup', (e) => {
  keys[e.key] = false;
});

Upvotes: 1

Spankied
Spankied

Reputation: 1885

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 & shift key pressed down 
  if(isKeyDown && keys[13] && keys[16]){
    console.log('enter + shift pressed')
  }
};

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

Upvotes: 1

Adrian
Adrian

Reputation: 11

The easiest way is use JQuery's keypress event and pass the value to a switch in order to know the multiple keys pressed:

    $(document).keypress(function(evt){
        var x = evt.which || evt.keyCode; 
        console.log(x);
    switch(evt.keyCode){
        case 119:
            //alert("Key press  \"W\"");
            //Go to North coordinates
        break;
        case 115:
            //alert("Key press \"S\"");
            //Go to South soordinates
        break;                
        case 97:
            //alert("Go to \"East\"");
        break;           
        case 100:
            //alert("Se presionó la flecha \"West\"");
            // ... 
        break; 
        case 113:
            ...
        break;
        case 101:
            ...
        break;       
        case 122:
            ...
        break;
        case 99:
            ...
        break;                
        case 13:
            ...
        break;}

You can set any key you want with their ascii code

Or if you want only JS try:

document.getElementById("container").addEventListener("keypress", myFunction);

function myFunction(evt) {
    var x = evt.which || evt.keyCode; 
    console.log(x);
    //Switch here
    //...
}

Maybe you need some flags in order to know wich key has pressed (or not).

Upvotes: 0

YetAnotherBot
YetAnotherBot

Reputation: 2086

For each key pressed, a new event will fire up and call your listener function.

To check, if at the time, there are multiple keys pressed, you could store the key value in a global array and compare.

So, for every keydown event you have to push the key value in a global array and for every keyup event remove that key value from the array.

Upvotes: 2

Amadan
Amadan

Reputation: 198324

No value can be both 87 and 65 at the same time; this is the reason your if will never trigger. If you press two keys "simultaneously", it will still fire two separate keydown events.

In order to detect 87 and 65 being pressed at the same time, you can do two different approaches:

  • Track last time each key was pressed. If e.g. 87 was pressed, and 65 was pressed a short time ago, trigger your code.

  • On keydown, note that the key is down. On keyup, note that the key is up. React when both 87 and 65 are down.

Upvotes: 4

Related Questions