Start · Sprachen · JavaScript · Referenz · XRSession: visibilitychange

XRSession: visibilitychange

Ereignis

Wird an eine <code>XRSession</code> gesendet, wenn sich ihr <code>visibilityState</code> ändert – also wenn sie sichtbar, versteckt oder sichtbar, aber ohne Fokus wird.

seit JavaScript WebXR Device API – Chromium-basierte Browser (Chro Kategorie: webapi

Signatur

xrSession.addEventListener("visibilitychange", handler)

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

Typ
void
Beschreibung
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);
Sichtbarkeit der XR-Sitzung: visible-blurred Sichtbarkeit der XR-Sitzung: visible

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;
  }
};
Sitzung ohne Fokus Audio fortgesetzt

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();
Listener entfernt

// 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: XRSessionEvent enthält nur session; den neuen Zustand immer aus session.visibilityState lesen.
  • Nicht mit document.visibilitychange verwechseln: 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 keine requestAnimationFrame-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 end werden keine weiteren Ereignisse gesendet – Listener dort aufräumen.