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:
window.addEventListener('keydown', function(event) {
if (event.keyCode === 37) {
//left arrow was pressed
}
}, 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:
Try key codes with this interactive test page
And find a list of keyCodes in this CSS Tricks article)
A lot of people think that the canvas element is not able to get key events. Many examples on the Web handle key events on canvas by adding a listener to the window object directly, like this:
Code source extract:
<canvas id="myCanvas" width="350" height="200">
</canvas>
<script>
function init() {
// This will work when you press a key, anywhere on the document
window.addEventListener('keydown', handleKeydown, false);
}
function handleKeydown(e){
alert('keycode: '+e.keyCode);
return false;
};
</script>
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...
Code:
<script>
var canvas, ctx;
var monsterX=100, monsterY=100, monsterAngle=0;
var incrementX = 0;
function init() {
// This function is called after the page is loaded
// 1 - Get the canvas
canvas = document.getElementById('myCanvas');
// 2 - Get the context
ctx=canvas.getContext('2d');
// 3 add key listeners to the window element
window.addEventListener('keydown', handleKeydown, false);
window.addEventListener('keyup', handleKeyup, false);
// 4 - start the animation
requestId = requestAnimationFrame(animationLoop);
}
function handleKeydown(evt) {
if (evt.keyCode === 37) {
//left key
incrementX = -1;
} else if (evt.keyCode === 39) {
// right key
incrementX = 1;
}
}
function handleKeyup(evt) {
incrementX = 0;
}
function animationLoop() {
// 1 - Clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2 Draw
drawMonster(monsterX, monsterY, monsterAngle, 'green', 'yellow');
// 3 Move
monsterX += incrementX;
// call again mainloop after 16.6 ms (60 frames/s)
requestId = requestAnimationFrame(animationLoop);
}
</script>
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:
<canvas id="myCanvas" width="350" tabindex="1" height="200">
</canvas>
And we force the canvas to get the focus with:
canvas=document.getElementById('myCanvas');
...
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.
Extract from the code:
var canvas;
function init() {
canvas=document.getElementById('myCanvas');
// This will work only if the canvas has the focus
canvas.addEventListener('keydown', handleKeydown, false);
// We can set the focus on the canvas like this:
//canvas.focus();
// ... but it will stop working if we click somewhere else
// in the document
}
function handleKeydown(e){
alert('keycode: '+e.keyCode);
return false;
};
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.
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.
Code:
function init() {
// This function is called after the page is loaded
// 1 - Get the canvas
canvas = document.getElementById('myCanvas');
// 2 - Get the context
ctx=canvas.getContext('2d');
// 3 - Add key listeners to the window element
canvas.addEventListener('keydown', handleKeydown, false);
canvas.addEventListener('keyup', handleKeyup, false);
canvas.addEventListener('mouseenter', setFocus, false);
canvas.addEventListener('mouseout', unsetFocus, false);
// 4 - Start the animation
requestId = requestAnimationFrame(animationLoop);
}
function setFocus(evt) {
canvas.focus();
};
function unsetFocus(evt) {
canvas.blur();
incrementX = 0; // stop the monster if the mouse exists the canvas
};
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."