Denis Potschien September 30th, 2014

HTML5: Pointer Lock API Lets You Hide the Mouse Pointer From View

Browsers are on the way to becoming full-fledged gaming platforms. Thanks to HTML5 and JavaScript developing complex applications is still loads of work, but possible. Quite a few game concepts don't rely on visible mouse pointers, though. Especially while controlling an app keyboard-based, a visible mouse pointer can get annoying. Use the new Pointer Lock API to simply hide it as necessary.

pointer-lock-api

Pointer Lock API: Simple Hide and Show on Click

The method „requestPointerLock()“, attached to any random element, requests the browser to hide the mouse pointer. The browser will do so, but not without any action from the user's side. That means you cannot hide the mouse pointer on page load. Instead use the „click“ event to call the method.

document.getElementsByTagName("canvas")[0].addEventListener("click", function() {
  this.requestPointerLock();
}, false);

In our example the mouse pointer will get hidden as soon as the user clicks the „<canvas>“ element. Similar to the browser's behavior in dealing with Fullscreen API, a pop-up will be shown that informs the user about the Pointer Locks API's attempt to hide the mouse pointer and allows to reshow it again by pressing the ESC key.

While the mouse pointer is deactivated aka hidden, it doesn't move anywhere but stays where you last left it. Any mouse movement will not lead to the pointer moving in any direction. This includes the inability to move the mouse outside the browser window. Mouse clicks will still get executed.

To recall the pointer's visibility the method „exitPointerLock()“ is our tool of choice. Used in conjunction with the property „pointerLockElement“ we can hide and show pointers by clicking on any element assigned to the operation. As soon as the pointer is hidden, the value of „pointerLockElement“ will be the DOM element to which the API got pointed. In all other cases the value will be „null“. Per e.g. „pointerLockElement.nodeName“ we could query the element's name - in this case we'd get „CANVAS“ as value.

document.getElementsByTagName("canvas")[0].addEventListener("click", function() {
  if (document.pointerLockElement == null) {
    this.requestPointerLock();
  } else {
    document.exitPointerLock();
  }
}, false);

In this example we check whether „pointerLockElement“ is „null“. That way we check whether the mouse pointer is hidden or shown.„requestPointerLock()“ or „exitPointerLock()“ are excuted accordingly. Other than „requestPointerLock()“ „exitPointerLock()“ does not require any user action. We don't have to start the method per „click“ event.

While „requestPointerLock()“ can be assigned to random elements, „exitPointerLock()“ must be assigned to „document“. Make sure to use the appropriate prefixes as the Pointer Lock API is fairly new - „webkitRequestPointerLock()“ and „webkitExitPointerLock()“ do the trick.

Pointer Lock API Advanced: Detecting the Movement of the Mouse Pointer

With the Pointer Lock API we get two new properties to detect mouse movement. What we already could do up to now was query the mouse coordinates (inside the browser window) using the event properties „clientX“ and „clientY“. The new properties „movementX“ and „movementY“ do more, they detect the motion of the mouse pointer, not just the position.

document.addEventListener("mousemove", function(e) {
  document.title = e.clientX + " " + e.movementX;
}

In this example we let a „mousemove“ event start a function that writes the recent values for „clientX“ and „movementX“ to the document title. While „clientX“ tells us the position at query time, „movementX“ tells us the mouse motion on the x-axis in relation to the last function call. The faster the mouse gets moved the higher the value for „movementX“ rises. Motion to the right („movementX“) and down („movementY“) will always give back a positive numeric value, while motion to the left and up will always produce a negative numeric value. If no motion is detected the value stays at zero.

In this case the values for „clientX“ and „clientY“ would also stay unchanged. They keep the values they had when the deactivation event occurred. The properties „movementX“ and „movementY“ have no dependency on the Pointer Lock API and can also be used with fully visible pointers.

Remember to prefix the new properties properly - e.g. with „webkitMovementX“ and „webkitMovementY“.

Pointer-Lock-API for Runaways: Reacting to Status Changes and Errors

The Pointer Lock API knows two event listeners. The first one called „pointerlockchange“ will always execute a function on either the mouse pointer being hidden or shown.

document.addEventListener("pointerlockchange", function() {
  if (document.pointerLockElement == null) {
    alert("The mouse pointer is now visible.");
  } else {
    alert("The mouse pointer is now hidden.");
  }
}, false);

This example leads to a dialogue window being shown on both occasions of showing and hiding the pointer. Using the property „pointerLockElement“ we detect the recent status and open the message accordingly.

The second event listener „pointerlockerror“ allows us to react to errors that might occur during hiding or showing the mouse pointer. As I mentioned earlier the browser will only react with hiding the pointer as long as the method „requestPointerLock()“ is called per „click“ event. Would we call „requestPointerLock()“ per „load“, the browser would not react with hiding, instead the event „pointerlockerror“ would be started.

document.addEventListener("pointerlockerror", function() {
  alert("I could not hide the mouse pointer.");
}, false);

„pointerlockchange“ and „pointerlockerror“ listen to the vendor specific variants as „webkitpointerlockchange“ and „webkitpointerlockerror“.

Browser Support

At the time of this writing the Pointer Lock API is supported by the desktop versions of Chrome and Firefox. Mobile browsers do not support the API at all, not even the mobile versions of Chrome and Firefox do. As the API has its strengths in gaming, chances are, people might be acceptant to having to install a given browser to be able to play that game they love. If so, the weak browser support wouldn't be too much of a problem.

(dpe)

Denis Potschien

Denis works as a freelance web designer since 2005.

One comment

  1. Wow, that is great. I was asking a friend of mine to do the same about an year back. He is a developer and he told me that it will take some bulky scripts to load along with my page to achieve that. But thanks to HTML5 now we can do that without executing heavy scripts… Actually I am an SEO and I am much concerned about load time.. BTW thanks for sharing such an helpful guide.

Leave a Reply

Your email address will not be published. Required fields are marked *