Start · Sprachen · JavaScript · Referenz · Document: pointerlockchange

Document: pointerlockchange

Ereignis

Wird am <code>Document</code> ausgelöst, sobald der Mauszeiger gesperrt (Pointer Lock aktiviert) oder wieder freigegeben wird.

seit JavaScript Baseline: alle modernen Browser (Chrome 37+, Firef Kategorie: webapi

Signatur

document.addEventListener("pointerlockchange", handler)

Beschreibung

Das Ereignis pointerlockchange gehört zur Pointer Lock API. Es wird am Document ausgelöst, wenn ein Element per Element.requestPointerLock() den Zeiger erfolgreich sperrt oder wenn die Sperre wieder aufgehoben wird – durch document.exitPointerLock(), durch Drücken der Esc-Taste, durch einen Fenster-/Tab-Wechsel oder durch Entfernen des gesperrten Elements aus dem DOM.

Das Ereignis selbst verrät nicht, ob gesperrt oder entsperrt wurde. Den aktuellen Zustand liest man über document.pointerLockElement aus: Ist der Wert ein Element, ist der Zeiger gesperrt; ist er null, ist die Sperre aufgehoben. Das Ereignis ist ein einfaches Event ohne zusätzliche Eigenschaften, ist nicht abbrechbar und bubbelt nicht.

Typische Einsatzgebiete sind 3D-Spiele (First-Person-Steuerung), CAD- und Modellierungswerkzeuge sowie 360°-Viewer. Im Handler wird meist ein mousemove-Listener registriert oder entfernt, der über movementX/movementY relative Bewegungen auswertet, und die Oberfläche (z. B. ein „Klicken zum Spielen“-Overlay) angepasst.

Registrieren lässt sich das Ereignis per document.addEventListener("pointerlockchange", handler) oder über die Eigenschaft document.onpointerlockchange. Schlägt das Sperren fehl, wird stattdessen pointerlockerror ausgelöst.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "pointerlockchange".
$handler Pflicht (event: Event) => void Callback, das bei jeder Änderung des Sperrzustands aufgerufen wird. Erhält ein generisches Event-Objekt.
$options boolean | AddEventListenerOptions false Optionale Listener-Optionen wie once, signal oder capture.

Beispiele

Sperrzustand per addEventListener überwachen

const canvas = document.querySelector('#game');

// Klick auf das Canvas fordert die Zeigersperre an
canvas.addEventListener('click', () => {
  canvas.requestPointerLock();
});

const onMouseMove = (e) => {
  console.log(`Δx: ${e.movementX}, Δy: ${e.movementY}`);
};

document.addEventListener('pointerlockchange', () => {
  if (document.pointerLockElement === canvas) {
    console.log('Zeiger gesperrt');
    document.addEventListener('mousemove', onMouseMove);
  } else {
    console.log('Zeiger freigegeben');
    document.removeEventListener('mousemove', onMouseMove);
  }
});
Zeiger gesperrt Δx: 4, Δy: -2 ... Zeiger freigegeben

Variante über die on-Property mit Pause-Overlay

const canvas = document.querySelector('#game');
const overlay = document.querySelector('#pause-overlay');
let paused = true;

overlay.addEventListener('click', () => canvas.requestPointerLock());

document.onpointerlockchange = () => {
  paused = document.pointerLockElement !== canvas;
  overlay.hidden = !paused;
  console.log(paused ? 'Spiel pausiert' : 'Spiel läuft');
};
Spiel läuft Spiel pausiert // nach Drücken von Esc

Listener mit AbortController wieder entfernen und Fehler abfangen

const canvas = document.querySelector('#viewer');
const controller = new AbortController();

const handleChange = () => {
  const locked = document.pointerLockElement !== null;
  canvas.classList.toggle('is-locked', locked);
  console.log('Gesperrt:', locked);
};

document.addEventListener('pointerlockchange', handleChange, { signal: controller.signal });
document.addEventListener('pointerlockerror', () => {
  console.warn('Zeigersperre konnte nicht aktiviert werden');
}, { signal: controller.signal });

canvas.addEventListener('click', async () => {
  try {
    // In neueren Browsern liefert requestPointerLock ein Promise
    await canvas.requestPointerLock({ unadjustedMovement: true });
  } catch (err) {
    console.warn('Fehler:', err.name);
  }
});

// Später, z. B. beim Verlassen der Ansicht:
const teardown = () => {
  document.exitPointerLock();
  controller.abort(); // entfernt beide Listener
};
Gesperrt: true Gesperrt: false

// Wichtig · Fallstricke

  • Kein Zustand im Event: Das Ereignis sagt nicht, ob gesperrt oder entsperrt wurde – immer document.pointerLockElement prüfen.
  • Am Document registrieren: Das Ereignis wird am Document ausgelöst, nicht am gesperrten Element. Ein Listener am Canvas bekommt nichts mit.
  • Nutzergeste erforderlich: requestPointerLock() funktioniert nur als Reaktion auf eine Nutzerinteraktion (z. B. Klick). Nach einem Verlassen per Esc blockieren Chrome und andere Browser ein erneutes Sperren für etwa eine Sekunde – dann kommt pointerlockerror statt pointerlockchange.
  • Promise-Rückgabe: Ab Chrome 92 / neueren Browsern gibt requestPointerLock() ein Promise zurück; ältere Browser liefern undefined. Die Option unadjustedMovement ist nicht überall verfügbar.
  • Einschränkungen: In iframes ist das Sandbox-Attribut allow-pointer-lock nötig. Auf Mobilgeräten und Touch-only-Geräten wird die API meist nicht unterstützt. Alte Präfix-Varianten (mozpointerlockchange, webkitpointerlockchange) sind veraltet.
  • Den mousemove-Listener bei Freigabe entfernen, um unnötige Verarbeitung und Speicherlecks zu vermeiden.