Signatur
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
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);
}
});
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();
}
});
// 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
clickführt zur Ablehnung des Promise. Das Promise immer mittry/catchbzw..catch()behandeln. - Vor dem Aufruf
vrDisplay.capabilities.canPresentprüfen – reine Orientierungssensoren (z. B. Cardboard ohne Präsentationsunterstützung) können nicht präsentieren. - Die Anzahl der Ebenen darf
capabilities.maxLayersnicht überschreiten;sourcemuss ein Canvas mit WebGL-Kontext sein. - Während der Präsentation
vrDisplay.requestAnimationFrame()stattwindow.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.