Start · Sprachen · JavaScript · Referenz · XRSession: end

XRSession: end

Ereignis

Wird an einer <code>XRSession</code> ausgelöst, sobald die WebXR-Sitzung beendet ist – ob durch <code>end()</code> der Anwendung oder durch den User Agent.

seit JavaScript WebXR Device API – Chromium-Browser (Chrome/Edge 7 Kategorie: webapi

Signatur

xrSession.addEventListener("end", handler)

Beschreibung

Das end-Ereignis meldet, dass eine WebXR-Sitzung (immersive-vr, immersive-ar oder inline) beendet ist. Es wird in zwei Fällen ausgelöst: wenn die Anwendung selbst XRSession.end() aufruft oder wenn der User Agent die Sitzung beendet. Das passiert zum Beispiel, wenn jemand das Headset abnimmt, mit der Systemtaste das immersive Erlebnis verlässt, die Seite wechselt oder das Gerät getrennt wird.

Das Ereignis ist vom Typ XRSessionEvent. Seine Eigenschaft session verweist auf die beendete Sitzung. Es bricht nicht ab (nicht cancelable) und steigt nicht auf (bubbelt nicht). Den Handler registrieren Sie mit addEventListener("end", …) oder über die Eigenschaft onend.

Nutzen Sie das Ereignis als zentrale Stelle zum Aufräumen: Referenzen auf die Sitzung und auf XRReferenceSpace-Objekte freigeben, eigene Zustände zurücksetzen, die Oberfläche anpassen (z. B. den Button „VR starten“ wieder anzeigen) und bei Bedarf die normale Render-Schleife mit window.requestAnimationFrame() fortsetzen. Weil die Sitzung auch ohne Zutun der Anwendung enden kann, reicht Aufräum-Code direkt nach end() nicht aus.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname, hier immer "end".
$handler Pflicht (event: XRSessionEvent) => void Callback, das ein XRSessionEvent erhält. event.session ist die beendete XRSession.
$options boolean | AddEventListenerOptions false Optionale Listener-Optionen, z. B. { once: true }. Das ist hier sinnvoll, weil jede Sitzung nur einmal endet.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler erhält ein XRSessionEvent mit der Eigenschaft session.

Beispiele

Sitzung starten und beim Ende aufräumen (addEventListener)

const button = document.querySelector('#enter-vr');
let xrSession = null;

const onSessionEnded = (event) => {
  console.log('XR-Sitzung beendet:', event.session === xrSession);
  xrSession = null;
  button.textContent = 'VR starten';
};

button.addEventListener('click', async () => {
  if (xrSession) {
    await xrSession.end(); // löst später das end-Ereignis aus
    return;
  }
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
    console.warn('immersive-vr wird nicht unterstützt');
    return;
  }
  xrSession = await navigator.xr.requestSession('immersive-vr');
  xrSession.addEventListener('end', onSessionEnded, { once: true });
  button.textContent = 'VR beenden';
});
XR-Sitzung beendet: true

onend-Eigenschaft und Rückkehr zur normalen Render-Schleife

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });

const drawScene = () => {
  gl.clearColor(0.1, 0.1, 0.1, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
};

const windowLoop = () => {
  drawScene();
  windowFrameId = requestAnimationFrame(windowLoop);
};
let windowFrameId = requestAnimationFrame(windowLoop);

const startXR = async () => {
  const session = await navigator.xr.requestSession('immersive-vr');
  cancelAnimationFrame(windowFrameId); // Fenster-Loop pausieren

  await session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
  const refSpace = await session.requestReferenceSpace('local');

  const xrLoop = (time, frame) => {
    const pose = frame.getViewerPose(refSpace);
    if (pose) drawScene();
    session.requestAnimationFrame(xrLoop);
  };
  session.requestAnimationFrame(xrLoop);

  session.onend = () => {
    console.log('Zurück zur 2D-Ansicht');
    windowFrameId = requestAnimationFrame(windowLoop);
  };
};

document.querySelector('#start').addEventListener('click', startXR);
Zurück zur 2D-Ansicht

Listener gezielt wieder entfernen

const handleEnd = () => console.log('Sitzung vorbei');

const session = await navigator.xr.requestSession('inline');
session.addEventListener('end', handleEnd);

// Später, z. B. wenn eine andere Komponente die Verwaltung übernimmt:
session.removeEventListener('end', handleEnd);

await session.end(); // Promise erfüllt sich, handleEnd wird NICHT mehr aufgerufen
console.log('end() abgeschlossen');
end() abgeschlossen

// Wichtig · Fallstricke

  • Nicht nur auf end() verlassen: Der User Agent kann die Sitzung jederzeit beenden, etwa über die Systemtaste, durch Abnehmen des Headsets oder durch einen Seitenwechsel. Aufräumen gehört daher immer in den end-Handler.
  • Nach dem Ereignis ist die Sitzung endgültig beendet. Sie lässt sich nicht fortsetzen, und session.requestAnimationFrame()-Callbacks laufen nicht mehr. Für eine neue Sitzung rufen Sie erneut navigator.xr.requestSession() auf, wofür bei immersiven Sitzungen wieder eine Nutzeraktion nötig ist.
  • Das Promise von XRSession.end() wird erfüllt, nachdem die Sitzung heruntergefahren ist. Verlassen Sie sich nicht auf eine bestimmte Reihenfolge zwischen der Promise-Auflösung und Ihrem Handler. Legen Sie die Aufräumlogik in den Handler.
  • Wird die Seite gerade entladen, ist nicht sicher, dass Ihr Handler noch vollständig ausgeführt wird. Verwenden Sie dort keine asynchrone Arbeit wie fetch, die zuverlässig abschließen muss. Nutzen Sie dafür z. B. navigator.sendBeacon().
  • Kompatibilität: WebXR steht nur in sicheren Kontexten (HTTPS) zur Verfügung und wird hauptsächlich von Chromium-Browsern und XR-Headset-Browsern unterstützt. Firefox und Desktop-Safari bieten es nicht an. Prüfen Sie deshalb vorher navigator.xr und isSessionSupported(). In iframes ist die Permissions-Policy xr-spatial-tracking nötig.