Signatur
Beschreibung
Die schreibgeschützte Eigenschaft pointerLockElement des ShadowRoot-Interfaces liefert das Element, an das während einer aktiven Zeigersperre alle Mausereignisse gehen. Die Eigenschaft stammt aus dem Mixin DocumentOrShadowRoot und entspricht Document.pointerLockElement, bezieht sich aber auf den jeweiligen Shadow-Baum.
Für Web Components ist das wichtig: document.pointerLockElement gibt aus Kapselungsgründen nicht das eigentliche Element im Shadow DOM zurück, sondern nur den Shadow-Host. Nur über shadowRoot.pointerLockElement kommt man an das konkrete innere Element, zum Beispiel ein <canvas> in einer 3D-Viewer-Komponente oder einem Spiel.
Der Wert wird umgelenkt (retargeting):
- Liegt das gesperrte Element direkt in diesem Shadow-Baum, bekommt man genau dieses Element.
- Liegt es in einem verschachtelten Shadow-Baum, bekommt man den Shadow-Host, der in diesem Baum liegt.
- Ist keine Sperre aktiv oder liegt das Element außerhalb dieses Shadow-Baums, ist der Wert
null.
Typischerweise fragt man die Eigenschaft im Handler für das Ereignis pointerlockchange ab, um festzustellen, ob die eigene Komponente die Sperre bekommen oder verloren hat.
Rückgabewert
null.Beispiele
Zeigersperre für ein Canvas in einer Web Component
class GameView extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({ mode: 'open' });
this.root.innerHTML = '<canvas width="400" height="300"></canvas>';
this.canvas = this.root.querySelector('canvas');
}
connectedCallback() {
this.canvas.addEventListener('click', () => this.canvas.requestPointerLock());
// pointerlockchange wird auf dem Document ausgelöst, nicht auf dem ShadowRoot
this.onLockChange = () => {
const locked = this.root.pointerLockElement === this.canvas;
console.log('Canvas gesperrt:', locked);
console.log('document.pointerLockElement:', document.pointerLockElement?.tagName);
};
document.addEventListener('pointerlockchange', this.onLockChange);
}
disconnectedCallback() {
document.removeEventListener('pointerlockchange', this.onLockChange);
}
}
customElements.define('game-view', GameView);
document.body.append(document.createElement('game-view'));
Mausbewegung nur bei aktiver Sperre auswerten
const host = document.querySelector('game-view');
const root = host.shadowRoot;
const canvas = root.querySelector('canvas');
let yaw = 0;
let pitch = 0;
document.addEventListener('mousemove', (event) => {
// Nur reagieren, wenn unser Canvas die Sperre hält
if (root.pointerLockElement !== canvas) return;
yaw += event.movementX * 0.2;
pitch = Math.max(-90, Math.min(90, pitch - event.movementY * 0.2));
console.log(`Blickrichtung: yaw=${yaw.toFixed(1)}, pitch=${pitch.toFixed(1)}`);
});
Sperre per Taste gezielt aufheben
const root = document.querySelector('game-view').shadowRoot;
document.addEventListener('keydown', (event) => {
if (event.key === 'p' && root.pointerLockElement) {
document.exitPointerLock();
console.log('Pause – Zeigersperre aufgehoben');
}
});
// Wichtig · Fallstricke
- Ereignisse auf dem Document:
pointerlockchangeundpointerlockerrorwerden auf demdocumentausgelöst, nicht auf demShadowRoot. Listener also dort registrieren und indisconnectedCallbackwieder entfernen. - Retargeting:
document.pointerLockElementgibt bei Elementen im Shadow DOM nur den Host zurück. Einen Vergleich mit dem inneren Element sollte man deshalb immer übershadowRoot.pointerLockElementmachen. - Geschlossene Shadow Roots: Bei
mode: 'closed'kommt man von außen nicht überhost.shadowRootan den Baum. Die Referenz muss man intern speichern, zum Beispiel als Rückgabewert vonattachShadow(). - Benutzergeste nötig:
requestPointerLock()funktioniert nur nach einer Benutzeraktion (etwa einem Klick). Mit Esc hebt der Browser die Sperre auf. Direkt danach lehnen manche Browser eine neue Anfrage kurz ab (pointerlockerror). - Kompatibilität: Wird von allen modernen Desktop-Browsern unterstützt. In Iframes braucht man
sandbox=\"allow-pointer-lock\". Auf Mobilgeräten wird Pointer Lock meist nicht unterstützt. In neueren Browsern gibtrequestPointerLock()ein Promise zurück, in älterenundefined.