Start · Sprachen · JavaScript · Referenz · VRDisplay.requestPresent()

VRDisplay.requestPresent()

Methode

Startet die Präsentation einer WebGL-Szene auf dem <code>VRDisplay</code> und gibt ein Promise zurück, das bei Erfolg erfüllt wird.

seit JavaScript WebVR 1.1 (veraltet, ersetzt durch WebXR Device AP deprecated seit ja Kategorie: webapi

Signatur

VRDisplay.prototype.requestPresent(layers)

Beschreibung

Die Methode requestPresent() des Interfaces VRDisplay weist ein VR-Headset an, den Inhalt eines oder mehrerer <canvas>-Elemente (über VRLayerInit-Objekte) stereoskopisch darzustellen. Erst nach erfolgreicher Präsentation liefert VRDisplay.requestAnimationFrame() Frames in der Bildwiederholrate des Headsets, und mit submitFrame() werden die gerenderten Bilder an das Gerät übergeben.

Der Aufruf muss in der Regel aus einer Benutzeraktion heraus erfolgen (z. B. einem click-Handler), sonst wird das Promise abgelehnt. Ruft man requestPresent() erneut auf, während bereits präsentiert wird, werden die Ebenen (Layers) ersetzt – so lässt sich die Canvas wechseln, ohne die Präsentation zu beenden.

Ob die Präsentation läuft, lässt sich über VRDisplay.isPresenting sowie über das Ereignis vrdisplaypresentchange auf window prüfen. Beendet wird sie mit VRDisplay.exitPresent().

Wichtig: Die gesamte WebVR-API ist veraltet und wurde nie standardisiert. Für neue Projekte sollte ausschließlich die WebXR Device API (navigator.xr.requestSession()) verwendet werden.

Parameter

Name Typ Default Beschreibung
$layers Pflicht Array<VRLayerInit> Array von VRLayerInit-Objekten mit source (ein HTMLCanvasElement bzw. OffscreenCanvas) sowie optional leftBounds und rightBounds (jeweils [x, y, breite, höhe] als Anteile von 0–1). Die maximale Anzahl ergibt sich aus VRDisplayCapabilities.maxLayers – praktisch meist 1.

Rückgabewert

Typ
Promise<void>
Beschreibung
Ein Promise, das erfüllt wird, sobald die Präsentation gestartet wurde. Es wird abgelehnt, wenn das Gerät nicht präsentieren kann (canPresent === false), die Ebenen ungültig sind oder keine Benutzeraktion vorlag.

Beispiele

Präsentation per Button-Klick starten

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

if (navigator.getVRDisplays) {
  navigator.getVRDisplays().then((displays) => {
    if (displays.length > 0) {
      vrDisplay = displays[0];
      button.disabled = !vrDisplay.capabilities.canPresent;
    }
  });
} else {
  console.warn('WebVR wird nicht unterstützt.');
}

button.addEventListener('click', async () => {
  try {
    // Muss innerhalb einer Benutzeraktion erfolgen
    await vrDisplay.requestPresent([{ source: canvas }]);
    console.log('Präsentation läuft:', vrDisplay.isPresenting);
  } catch (err) {
    console.error('requestPresent fehlgeschlagen:', err);
  }
});
Präsentation läuft: true

Canvas-Größe an das Headset anpassen und Render-Schleife starten

const startVR = async (vrDisplay, canvas, gl) => {
  await vrDisplay.requestPresent([{ source: canvas }]);

  // Canvas für beide Augen nebeneinander dimensionieren
  const left = vrDisplay.getEyeParameters('left');
  const right = vrDisplay.getEyeParameters('right');
  canvas.width = Math.max(left.renderWidth, right.renderWidth) * 2;
  canvas.height = Math.max(left.renderHeight, right.renderHeight);

  const frameData = new VRFrameData();

  const onFrame = () => {
    if (!vrDisplay.isPresenting) return;
    vrDisplay.requestAnimationFrame(onFrame);
    vrDisplay.getFrameData(frameData);

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    // linkes Auge
    gl.viewport(0, 0, canvas.width / 2, canvas.height);
    // ... Szene mit frameData.leftViewMatrix zeichnen
    // rechtes Auge
    gl.viewport(canvas.width / 2, 0, canvas.width / 2, canvas.height);
    // ... Szene mit frameData.rightViewMatrix zeichnen

    vrDisplay.submitFrame();
  };

  vrDisplay.requestAnimationFrame(onFrame);
};

Präsentationswechsel beobachten und beenden

window.addEventListener('vrdisplaypresentchange', (event) => {
  const { display } = event;
  console.log(display.isPresenting ? 'VR-Modus aktiv' : 'VR-Modus beendet');
});

document.querySelector('#exit-vr').addEventListener('click', async () => {
  if (vrDisplay?.isPresenting) {
    await vrDisplay.exitPresent();
  }
});
VR-Modus aktiv VR-Modus beendet

// Wichtig · Fallstricke

  • Veraltet: WebVR ist aus allen aktuellen Browsern entfernt bzw. war nur hinter Flags (Chrome) oder in älteren Firefox-Versionen unter Windows verfügbar. Für neue Projekte navigator.xr.requestSession('immersive-vr') der WebXR Device API verwenden; ältere Projekte lassen sich mit dem WebXR-Polyfill migrieren.
  • Benutzeraktion erforderlich: Ein Aufruf außerhalb eines Ereignis-Handlers wie click führt zur Ablehnung des Promise. Das Promise immer mit try/catch bzw. .catch() behandeln.
  • Vor dem Aufruf vrDisplay.capabilities.canPresent prüfen – reine Orientierungssensoren (z. B. Cardboard ohne Präsentationsunterstützung) können nicht präsentieren.
  • Die Anzahl der Ebenen darf capabilities.maxLayers nicht überschreiten; source muss ein Canvas mit WebGL-Kontext sein.
  • Während der Präsentation vrDisplay.requestAnimationFrame() statt window.requestAnimationFrame() nutzen, da letzteres an die Monitorfrequenz gebunden ist und im Headset ruckelt.
  • Funktioniert nur in sicheren Kontexten (HTTPS) und kann durch Feature-Policy/Permissions-Policy in iframes blockiert sein.