Listen to some programs

I am trying to allow a user to move an element on a page using the arrow keys. So far I have had a movement working on up / down / left / right, but not on the diagonal (two arrow keys at the same time).

My listener looks like this:

addEventListener('keydown', function(e){ move = false; x = false; y = false; var keycode; if (window.event) keycode = window.event.keyCode; else if (e) keycode = e.which; switch(keycode){ case 37: move = true; x = 'negative'; //prevent page scroll e.preventDefault() break; case 38: move = true; y = 'negative' //prevent page scroll e.preventDefault() break; case 39: move = true; x = 'positive' //prevent page scroll e.preventDefault() break; case 40: move = true; y = 'positive' //prevent page scroll e.preventDefault() break; } if(move){ animation.move(x,y); } return false; }) 

The idea was that if the user presses the arrow key, he sets x and y both negative and positive and runs the move () function, which will move the element to the preset the number of pixels in the desired direction, and if two keys were pressed , the second event would be missed ... I also hope that the user will be able to change direction without visible changes by quickly releasing and pressing the keys. None of them happen, however, if the user presses a key in a different direction, they seem to need to wait for the moment when the movement occurs, if they do not completely release the key, and then press another and he will not answer the second key at all. until the first is released.

+6
source share
3 answers

Fiddle: http://jsfiddle.net/ATUEx/

Create a temporary cache to remember your strokes.

The implementation of the processing of the two keys will follow this pattern:

  • <keydown>
    • Delete previous timeout.
    • Check if a key code has been cached.
      If yes, and a valid combination:
      - Delete all cached key codes
      - Execute function for this combination
      yet
      - Delete all cached key codes
      - Save new key code
      - Set a timeout to clear key codes (see below) with a reasonable delay
  • Repeat 1

Reasonable delay: an experiment to find out which timeout is enough for you. When the delay is too short, the next triggered event will not find the previously entered key code.

When the delay is too long, key strokes will flock when you don't want it.


the code

I created an efficient function by keeping your code in mind. You should be able to implement it very easily.

 (function(){ //Anonymous function, no leaks /* Change the next variable if necessary */ var timeout = 200; /* Timeout in milliseconds*/ var lastKeyCode = -1; var timer = null; function keyCheck(ev){ var keyCode = typeof ev.which != "undefined" ? ev.which : event.keyCode; /* An alternative way to check keyCodes: * if(keyCode >= 37 && keyCode <= 40) ..*/ /*37=Left 38=Up 39=Right 40=Down */ if([37, 38, 39, 40].indexOf(keyCode) != -1){ /* lastKeyCode == -1 = no saved key Difference betwene keyCodes == opposite keys = no possible combi*/ if(lastKeyCode == -1 || Math.abs(lastKeyCode - keyCode) == 2){ refresh(); lastKeyCode = keyCode; } else if(lastKeyCode == keyCode){ clear([lastKeyCode]); } else { /* lastKeyCode != -1 && keyCode != lastKeyCode and no opposite key = possible combi*/ clear([lastKeyCode, keyCode]); lastKeyCode = -1 } ev.preventDefault(); //Stop default behaviour ev.stopPropagation(); //Other event listeners won't get the event } /* Functions used above, grouped together for code readability */ function reset(){ keyCombi([lastKeyCode]); lastKeyCode = -1; } function clear(array_keys){ clearTimeout(timer); keyCombi(array_keys); } function refresh(){ clearTimeout(timer); timer = setTimeout(reset, timeout); } } var lastX = false; var lastY = false; function keyCombi(/*Array*/ keys){ /* Are the following keyCodes in array "keys"?*/ var left = keys.indexOf(37) != -1; var up = keys.indexOf(38) != -1; var right = keys.indexOf(39) != -1; var down = keys.indexOf(40) != -1; /* What direction? */ var x = left ? "negative" : right ? "positive" : false; var y = up ? "negative" : down ? "positive" : false; /* Are we heading to a different direction?*/ if(lastX != x || lastY != y) animation.move(x, y); lastX = x; lastY = y; } //Add event listener var eventType = "keydown";window["on"+eventType] = keyCheck; })(); 

A keydown event listener has been added at the end of the anonymous function. This event is fired only once (when the key is pressed). When the second key is pressed fast enough, the code recognizes two keystrokes one after another and calls keyCombi() .

I designed keyCombi to be intelligent and only call animation.move(x,y) when the values ​​change. In addition, I realized the ability to use two directions at the same time.

Note I have included functions in the shell of anonymous functions, so the variables are not defined in the global ( window ) area. If you do not need a field of view, feel free to delete the first and last line.

+8
source

Here is your code for you, slightly reworked ... http://jsfiddle.net/w8uNz/ It just WORKS. Moves an element over its parent element.

Rob W is right, you must have a dynamic cache of keys pressed for a certain period of time. But for what? if you are doing a dynamic game, there must be a much higher abstraction for this. And overall, you need to improve your coding level if you want to do something like that. (Or it will just generate headaches for you.)

+2
source

Logically, this sounds pretty simple:

  • the first key fires an event with a keystroke, saves this event on the stack
  • then the second key fires the down event, saves this event on the stack
  • now you have two keystrokes and no key
  • If the key fires, you have three options
    • you have only one event => go in that direction
    • you have two events => go diagonally
    • you have more than two events or an invalid parameter (for example, right and left) => do nothing or something else that you like
  • clear stack
+1
source

Source: https://habr.com/ru/post/898397/


All Articles