Signatur
Beschreibung
Das Ereignis visibilitychange wird an einer XRSession ausgelöst, sobald sich deren Eigenschaft XRSession.visibilityState ändert. Möglich sind drei Zustände: "visible" (Inhalte werden angezeigt, Eingaben kommen an), "visible-blurred" (Inhalte sind sichtbar, aber etwa ein Systemdialog oder ein Overlay liegt darüber, Eingaben werden nicht zugestellt und die Bildrate kann gedrosselt sein) und "hidden" (die Inhalte sind für den Benutzer nicht sichtbar).
Das Ereignis ist ein XRSessionEvent; über event.session erhält man die betroffene Sitzung. Der neue Zustand steht nicht im Ereignis selbst, sondern wird aus event.session.visibilityState gelesen. Den Handler registriert man entweder per addEventListener("visibilitychange", …) oder über die Eigenschaft onvisibilitychange.
Typische Einsatzzwecke: Spiellogik oder Physiksimulation pausieren, Audio stummschalten, Timer anhalten, ressourcenintensive Berechnungen aussetzen oder Eingabe-Hinweise ausblenden, solange die Sitzung nicht im Vordergrund ist. Da bei "visible-blurred" keine Eingabequellen-Ereignisse (select, squeeze) eintreffen, sollte die Anwendung dann keine Benutzeraktion erwarten.
Wichtig: Dieses Ereignis ist unabhängig vom gleichnamigen document-Ereignis der Page Visibility API. Eine immersive Sitzung kann versteckt sein, während das Dokument als sichtbar gilt – und umgekehrt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "visibilitychange". |
|
| $handler Pflicht | (event: XRSessionEvent) => void | Callback, der ein XRSessionEvent erhält. event.session verweist auf die betroffene XRSession. |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Listener-Optionen wie once oder signal (zum Entfernen per AbortController). |
Rückgabewert
addEventListener() gibt nichts zurück. Der Handler erhält ein XRSessionEvent; der aktuelle Zustand steht in event.session.visibilityState ("visible" | "visible-blurred" | "hidden").Beispiele
Spiel bei Sichtbarkeitswechsel pausieren (addEventListener)
const startXR = async () => {
const session = await navigator.xr.requestSession('immersive-vr');
let paused = false;
session.addEventListener('visibilitychange', (event) => {
const state = event.session.visibilityState;
console.log('Sichtbarkeit der XR-Sitzung:', state);
// Nur im Zustand "visible" läuft die Spiellogik weiter
paused = state !== 'visible';
});
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
if (!paused) {
// updateGame(time, frame);
}
// renderScene(frame);
};
session.requestAnimationFrame(onFrame);
};
document.querySelector('#enter-vr').addEventListener('click', startXR);
Audio über die on-Property steuern
const audioCtx = new AudioContext();
const session = await navigator.xr.requestSession('immersive-ar');
session.onvisibilitychange = async ({ session }) => {
switch (session.visibilityState) {
case 'hidden':
await audioCtx.suspend();
console.log('Audio angehalten');
break;
case 'visible-blurred':
// Systemmenü offen: Lautstärke nur absenken wäre auch denkbar
console.log('Sitzung ohne Fokus');
break;
case 'visible':
await audioCtx.resume();
console.log('Audio fortgesetzt');
break;
}
};
Listener mit AbortController wieder entfernen
const session = await navigator.xr.requestSession('immersive-vr');
const controller = new AbortController();
const onVisibility = (event) => {
console.log('Zustand:', event.session.visibilityState);
};
session.addEventListener('visibilitychange', onVisibility, {
signal: controller.signal,
});
// Beim Beenden der Sitzung aufräumen
session.addEventListener('end', () => {
controller.abort(); // entspricht removeEventListener('visibilitychange', onVisibility)
console.log('Listener entfernt');
}, { once: true });
// Später z. B.: await session.end();
// Wichtig · Fallstricke
- Browser-Unterstützung: WebXR und damit dieses Ereignis sind nur in Chromium-basierten Browsern und XR-Browsern (z. B. Meta Quest Browser) verfügbar; Firefox und Safari (Desktop) unterstützen WebXR nicht. Zudem ist ein sicherer Kontext (HTTPS) erforderlich. Prüfen Sie vorab mit
navigator.xr?.isSessionSupported(). - Kein Zustand im Ereignis:
XRSessionEvententhält nursession; den neuen Zustand immer aussession.visibilityStatelesen. - Nicht mit
document.visibilitychangeverwechseln: Die Sichtbarkeit der XR-Sitzung ist unabhängig vom Dokument. Für immersive Sitzungen ist das Sitzungs-Ereignis maßgeblich. - Im Zustand
"hidden"werden in der Regel keinerequestAnimationFrame-Callbacks der Sitzung aufgerufen; bei"visible-blurred"kann die Bildrate gedrosselt sein und Eingabeereignisse bleiben aus. Zeitbasierte Logik sollte daher große Zeitsprünge (Delta-Time) abfangen. - Bei Inline-Sitzungen (
"inline") folgt der Zustand im Wesentlichen der Sichtbarkeit des Dokuments. - Nach
endwerden keine weiteren Ereignisse gesendet – Listener dort aufräumen.