11

I've been looking for a solution in this forum, but not found yet. I need to keep the focus on a canvas element always, no matter where i click on the page. I have several buttons, and inside each onclick event i write:

document.getElementById('canvas').focus();

This does the trick, but i think is not the best practise. Any idea?

Rok Anne Roll
  • 123
  • 1
  • 1
  • 10
  • read about `onblur` event – Iłya Bursov May 01 '15 at 18:23
  • I´ve tried with the onblur event over the canvas but seems to work only with the input element. – Rok Anne Roll May 01 '15 at 18:37
  • Could you detail a little more about *why* you need the focus on canvas? Is it to catch mouse moves, keys? –  May 01 '15 at 18:57
  • Nop, i 'm coding an html5 tetris game and i have some buttoms to control the play/pause game and other butttons to control sounds and music, when i click on these buttons i lose the focus on the canvas element, and this fact makes that strange things happend on the behaviour. But calling the focus method, as explained above, on each of the onclick events, makes everything works great. But this seems to be an ugly solution. – Rok Anne Roll May 01 '15 at 19:07
  • @RokAnneRoll ok. I outlined one approach below in my answer. Just activate the demo window by clicking in it first and all keys etc. will be redirected to the canvas element. Optionally, set a tabindex for the canvas element (I incl. a link to to demonstrate this as well). –  May 01 '15 at 19:12

4 Answers4

17

Canvas elements are not focusable by default. You need to set a tabIndex for it first.

Example

document.querySelector("canvas").onblur = function() {
    var me = this;
    me.style.background = "red";
    setTimeout(function() {
        me.style.background = "transparent";
        me.focus();
    }, 500);
}
canvas {border:1px solid #000}
Click on canvas then outside - a blur event will be thrown coloring the background red for half a second:<br>
<canvas tabindex=0 ></canvas>

However, I cannot really see any reason why you would need to force focus on the canvas element.

If you want to catch mouse and key events there are better ways to do it by for example prevent an event from bubbling up. Forcing focus will also prevent input fields from working, accessibility and so forth.

Here is one way you can catch mouse moves and key down events and redirect them to canvas use:

Example "hijacking" events

var ctx = document.querySelector("canvas").getContext("2d");

// redirect events
window.addEventListener("mousemove", function(e) {
    var rect = ctx.canvas.getBoundingClientRect(),
        x = e.clientX - rect.left,
        y = e.clientY - rect.top;
  
  ctx.fillRect(x-2, y-2, 4, 4);
});

window.addEventListener("keydown", function(e) {
  e.preventDefault();
  ctx.fillText(e.keyCode, Math.random() * 300, Math.random() * 150);
});
html, body {width:100%;height:100%;margin:0;overflow:hidden}
canvas {border:1px solid #000}
<h1>Demo</h1>
<p>Active this window by clicking in it, then hit some keys and move mouse around</p>
<canvas tabindex=0></canvas>
<h2>End</h2>
<button>Test button</button>
1

using jQuery , you can use trigger()

$("#canvas").trigger("click");
  • 2
    Not correct, canvas do also have blur but you need to set tabIndex for it first. http://jsfiddle.net/epistemex/a910mv6a/ –  May 01 '15 at 19:10
  • @KenFyrstenberg you are right , will edit my answer , thanks for info. – Mohmad Taher May 10 '15 at 14:00
0

What about this (using jQuery):

$('#canvas').focus().blur(function() {
    $('#canvas').focus();
});

The idea is to give it the focus back every time it loses it (blur).

I made an example (with a textbox which is basically the same) here: http://jsfiddle.net/thepeak/j02vyryf/

  • 1
    You should try with an actual canvas element –  May 01 '15 at 18:36
  • Wow, you're right, it doesn't work... Canvas apparently don't have onblur... I should've tested it on a canvas... sorry!!! – Martin E. Zulliger May 01 '15 at 18:47
  • Yes...i have tried with jquery too but nothing happends. Thanks for the attempt Martin. – Rok Anne Roll May 01 '15 at 18:50
  • Ok! what about: `$(document).click(function() { $('#canvas').focus(); });` That will work unless the button... has already an onclick event in that case... *sigh* – Martin E. Zulliger May 01 '15 at 18:59
  • 1
    @MartinE.Zulliger I does have an onblur, you just need to set tabIndex for the element first (I know, it's kind of subtle :) ) –  May 01 '15 at 19:13
  • @KenFyrstenberg Oh I didn't know that, thanks! Wait, if Rok Anne sets the tabindex and then uses onblur to set the focus back, isn't that it? – Martin E. Zulliger May 01 '15 at 19:17
  • 1
    @MartinE.Zulliger yes, but you need to give it a small timeout before setting focus() (I added an example in my answer, though 500ms for the sake of demo). –  May 01 '15 at 19:20
0

The newest Pointer Lock Api, is doing exactly as the OP query, in 2015.

To acquire the lock, a user interaction is required, and to exit the lock, we have to Ctrl + z, or press escape.

Demo: https://mdn.github.io/dom-examples/pointer-lock/

enter image description here

Mdn: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API#simple_example_walkthrough


Base code to query the pointer lock, requiring a user interaction:

if(document.pointerLockElement === canvas ||
  document.mozPointerLockElement === canvas) {
    console.log('The pointer lock status is now locked');
} else {
    console.log('The pointer lock status is now unlocked');
}

canvas.onclick = function() {
  canvas.requestPointerLock();
}
NVRM
  • 11,480
  • 1
  • 88
  • 87