Mouse Pointer Lock in HTML: Video and Sample Code

After watching Paul Irish’s talk at SXSW, I got curious about the new pointer lock APIs in Chrome and decided to create a sample application. Pointer lock refers to the ability to lock the mouse pointer in one location and hide it while still getting certain mouse events like mousemove. This is critical for immersive experiences like games since the user wants to be able to use the mouse to navigate, but doesn’t want the pointer to move off the screen or get in the way.

It’s still early days for navigator.webkitPointer, but I was able to get something to work with Chrome Canary. First, a video demo, then some explanation:


If you want to try the demo firsthand (and maybe experiment with the pointer lock APIs yourself), you can find the code here. But first, you need to follow these steps:

  1. Download Chrome Canary.
  2. Enable pointer lock:
    1. Type "chrome://flags" into your location bar.
    2. Scroll down to "Enable Pointer Lock Mac, Windows, Linux, Chrome OS".
    3. Click "Enable".
    4. Click the "Relaunch Now" button at the bottom to relaunch Chrome Canary.
  3. Allow sites to disable the mouse cursor:
    1. Open settings.
    2. Click "Show advanced settings…".
    3. Click "Content settings…"
    4. Scroll down to the "Mouse Cursor" section.
    5. Select "Allow all sites to disable the mouse cursor". In theory, you should be able to select "Ask me when a site tries to disable the mouse cursor (recommended)," however this isn’t working for me right now (remember: still early days).

Currently, you can only lock the mouse pointer in Chrome while in fullscreen mode. Here’s the relevant code:

document.addEventListener('webkitfullscreenchange', onFullscreenChange, false);

function onFullscreen(event) {
    document.body.webkitRequestFullScreen();
}

function onFullscreenChange(event) {
    if (document.webkitIsFullScreen) {
        id('fullscreenButton').style.display = 'none';
        if (navigator.webkitPointer) navigator.webkitPointer.lock(document.body);
    } else {
        if (navigator.webkitPointer) navigator.webkitPointer.unlock();
        id('fullscreenButton').style.display = 'block';
    }
}

Remember that you have to handle mouse coordinates differently when the pointer is locked versus when the pointer is visible. When it’s locked, even though you can’t see the mouse cursor, it’s actually frozen in one location so it can’t be moved out of the window or onto another monitor which means properties on MouseEvent like clientX and clientY are useless. Instead, you can use properties like webkitMovementX and webkitMovementY that tell you how much (and in which direction) the mouse is being moved as opposed to the location of the mouse cursor. Below is the relevant code from the sample application:

var lastMouse;

function onMouseMove(event) {
    var xDelta, yDelta;
    if (navigator.webkitPointer && navigator.webkitPointer.isLocked) {
        xDelta = event.webkitMovementX;
        yDelta = event.webkitMovementY;
    } else {
        if (lastMouse == null) lastMouse = {x:event.clientX, y:event.clientY};
        xDelta = event.clientX - lastMouse.x;
        yDelta = event.clientY - lastMouse.y;
    }
}