Dealing with key events

Dealing with key events

INTRODUCTION

When you listen to keyboard related events (keydown, keyup or keypressed), the event parameter passed to the listener function will contain the code of the key that fired the event. Then it is possible to test what key has been pressed or released, like this:

  1. window.addEventListener(‘keydown’, function(event) {
  2.    if (event.keyCode === 37) {
  3.      //left arrow was pressed
  4.    }
  5. }, false);

At line 2, the value “37” is the key code that corresponds to the left arrow. It might be difficult to know the correspondences between real keyboard keys and codes, so here are handy pointers:

EXAMPLE 1: ADDING A KEY LISTENER TO THE WINDOW OBJECT:

Online example: http://jsbin.com/voviva/2/edit

Extract from source code:

  1. <canvas id=“myCanvas” width=“350” height=“200”>
  2. </canvas>
  3.  
  4. function init() {
  5.     // This will work when you press a key, anywhere on the document
  6.     window.addEventListener(‘keydown’, handleKeydown, false);
  7. }
  8.  
  9.  
  10. function handleKeydown(e){
  11.     alert(‘keycode: ‘+e.keyCode);
  12.     return false;
  13. };

Indeed this solution works well if you write a game, and want to detect events wherever the mouse cursor is, and without worrying about what HTML element has the focus, etc…

Move the monster with the keyboard

Online example at JS Bin

Extract from source code:

  1. var canvas, ctx;
  2. var monsterX=100, monsterY=100, monsterAngle=0;
  3. var incrementX = 0;
  4. function init() {
  5.     // This function is called after the page is loaded
  6.  
  7.     // 1 – Get the canvas
  8.     canvas = document.getElementById(‘myCanvas’);
  9.  
  10.     // 2 – Get the context
  11.     ctx=canvas.getContext(‘2d’);
  12.  
  13.     // 3 add key listeners to the window element
  14.     window.addEventListener(‘keydown’, handleKeydown, false);
  15.     window.addEventListener(‘keyup’, handleKeyup, false);
  16.     // 4 – start the animation
  17.     requestId = requestAnimationFrame(animationLoop);
  18. }
  19. function handleKeydown(evt) {
  20.     if (evt.keyCode === 37) {
  21.        //left key
  22.        incrementX = 1;
  23.     } else if (evt.keyCode === 39) {
  24.        // right key
  25.        incrementX = 1;
  26.     }
  27. }
  28. function handleKeyup(evt) {
  29.     incrementX = 0;
  30. }
  31. function animationLoop() {
  32.     // 1 – Clear
  33.     ctx.clearRect(0, 0, canvas.width, canvas.height);
  34.  
  35.     // 2 Draw
  36.     drawMonster(monsterX, monsterY, monsterAngle, ‘green’, ‘yellow’);
  37.  
  38.     // 3 Move
  39.     monsterX += incrementX;
  40.  
  41.     // call again mainloop after 16.6 ms (60 frames/s)
  42.     requestId = requestAnimationFrame(animationLoop);
  43. }

EXAMPLE 2: WHAT IF I WANT TO LISTEN TO KEY EVENTS ONLY IN MY CANVAS?

If you add a key listener to a canvas element, the problem is that it will get events only when it has the focus. And by default, it will never have the focus!

The tabindex attribute of the canvas element makes it focusable. Without it, it will never get the focus!

The trick is to declare the canvas like this:

  1. <canvas id=“myCanvas” width=“350” tabindex=“1” height=“200”>
  2. </canvas>

And we force the canvas to get the focus with:

  1. canvas=document.getElementById(‘myCanvas’);
  2. canvas.focus();

Now, if we try an example with the above canvas declaration, we show when an HTML element has the focus: a border is added to it, as shown here: http://jsbin.com/cohide/2/edit.

Note that the line that forces the focus to the canvas is commented by default. Try to click on the canvas, then press a key, then click out of the canvas, then press a key: this time nothing happens!

Extract from the code:

  1. var canvas;
  2. function init() {
  3.      canvas=document.getElementById(‘myCanvas’);
  4.  
  5.      // This will work only if the canvas has the focus
  6.      canvas.addEventListener(‘keydown’, handleKeydown, false);
  7.      // We can set the focus on the canvas like this:
  8.      //canvas.focus();
  9.      // … but it will stop working if we click somewhere else
  10.      // in the document
  11. }
  12.  
  13.  
  14. function handleKeydown(e){
  15.      alert(‘keycode: ‘+e.keyCode);
  16.      return false;
  17. };

Line 10 is useful to initially set the focus on the canvas, but this trick will not work if we click somewhere else in the HTML page.

EXAMPLE 3: A BETTER WAY: SET THE FOCUS WHEN THE MOUSE CURSOR ENTERS THE CANVAS

A better way to manage key events on a canvas is to set the focus when the mouse is over the canvas, and to un-focus it otherwise.

Here is a modified version of the “move monster example” seen earlier. This time, you move the monster with the left and right arrow only when the mouse cursor is over the canvas. We added two mouse event listeners on the canvas: one for the mouseenter event and the other for the mouseout event.

When the mouse enters the canvas we call canvas.focus() to set the focus to the canvas, and when the mouse cursor goes out of the canvas, we call canvas.blur() to unset the focus.

Online example at JS Bin

Extract from the code:

  1. function init() {
  2.    // This function is called after the page is loaded
  3.    // 1 – Get the canvas
  4.    canvas = document.getElementById(‘myCanvas’);
  5.    // 2 – Get the context
  6.    ctx=canvas.getContext(‘2d’);
  7.    // 3 – Add key listeners to the window element
  8.    canvas.addEventListener(‘keydown’, handleKeydown, false);
  9.    canvas.addEventListener(‘keyup’, handleKeyup, false);
  10.    canvas.addEventListener(‘mouseenter’, setFocus, false);
  11.    canvas.addEventListener(‘mouseout’, unsetFocus, false);
  12.    // 4 – Start the animation
  13.    requestId = requestAnimationFrame(animationLoop);
  14. }
  15. function setFocus(evt) {
  16.     canvas.focus();
  17. };
  18. function unsetFocus(evt) {
  19.    canvas.blur();
  20.    incrementX = 0; // stop the monster if the mouse exists the canvas
  21. };

The third parameter (false) of lines 12 and 13 means “we do not want to propagate the event to the ancestors of the canvas in the DOM.”

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s