Start · Sprachen · JavaScript · Referenz · XRLayerEvent

XRLayerEvent

Schnittstelle

Ereignistyp der WebXR Layers API, der bei Zustandsänderungen einer <code>XRLayer</code> ausgelöst wird, vor allem beim <code>redraw</code>-Ereignis, wenn der Inhalt einer Ebene neu gezeichnet werden muss.

seit JavaScript Experimentell: WebXR Layers API (Chromium-basierte Kategorie: webapi

Signatur

interface XRLayerEvent extends Event

Beschreibung

XRLayerEvent gehört zum Modul WebXR Layers der WebXR Device API. Das Interface erweitert Event um die schreibgeschützte Eigenschaft layer. Diese verweist auf die XRLayer, die das Ereignis ausgelöst hat. Wichtigster Anwendungsfall ist das Ereignis redraw. Es wird auf Kompositionsebenen (XRCompositionLayer) wie XRQuadLayer, XRCylinderLayer, XREquirectLayer oder XRCubeLayer ausgelöst.

Kompositionsebenen werden vom XR-Compositor unabhängig vom normalen Frame-Rendering dargestellt. Deshalb zeichnet man statische Inhalte wie Menüs, Texttafeln oder Skyboxen in der Regel nur einmal und nicht in jedem Frame. Das Laufzeitsystem kann den Inhalt der Textur aber verwerfen, etwa wenn die Sitzung pausiert oder der GPU-Kontext wiederhergestellt wird. Dann setzt es layer.needsRedraw auf true und löst redraw aus. Die Anwendung sollte daraufhin im nächsten requestAnimationFrame-Callback den Inhalt der Ebene neu zeichnen.

Einen Listener registrierst du entweder mit layer.addEventListener("redraw", handler) oder über die Eigenschaft layer.onredraw. Den Konstruktor new XRLayerEvent(type, eventInitDict) brauchst du nur selten, etwa für Tests oder selbst ausgelöste Ereignisse.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, für Browser-Ereignisse immer "redraw".
$eventInitDict Pflicht XRLayerEventInit Objekt mit der Pflicht-Eigenschaft layer (die betroffene XRLayer) sowie optional bubbles, cancelable und composed aus EventInit.

Rückgabewert

Typ
XRLayerEvent
Beschreibung
Das Ereignisobjekt. event.layer (nur lesbar) liefert die XRLayer, auf die sich das Ereignis bezieht.

Beispiele

Quad-Ebene nur bei Bedarf neu zeichnen (addEventListener)

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

const session = await navigator.xr.requestSession('immersive-vr', {
  requiredFeatures: ['layers']
});
const refSpace = await session.requestReferenceSpace('local');
const binding = new XRWebGLBinding(session, gl);

const menuLayer = binding.createQuadLayer({
  space: refSpace,
  viewPixelWidth: 1024,
  viewPixelHeight: 512,
  layout: 'mono'
});
const projLayer = binding.createProjectionLayer();
session.updateRenderState({ layers: [projLayer, menuLayer] });

let menuDirty = true;
menuLayer.addEventListener('redraw', (event) => {
  console.log('Neu zeichnen nötig für:', event.layer.constructor.name);
  menuDirty = true;
});

const fb = gl.createFramebuffer();
const onFrame = (time, frame) => {
  session.requestAnimationFrame(onFrame);
  if (menuDirty || menuLayer.needsRedraw) {
    const sub = binding.getSubImage(menuLayer, frame);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D, sub.colorTexture, 0);
    gl.viewport(sub.viewport.x, sub.viewport.y, sub.viewport.width, sub.viewport.height);
    gl.clearColor(0.1, 0.2, 0.4, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    menuDirty = false;
  }
};
session.requestAnimationFrame(onFrame);
Neu zeichnen nötig für: XRQuadLayer

Handler über onredraw setzen und wieder entfernen

// Annahme: cylinderLayer wurde per binding.createCylinderLayer() erzeugt
const handleRedraw = (event) => {
  console.log('Zylinder-Ebene verloren – neu zeichnen');
  scheduleRedraw(event.layer);
};

// Variante 1: Event-Handler-Eigenschaft
cylinderLayer.onredraw = handleRedraw;

// Variante 2: addEventListener / removeEventListener
cylinderLayer.addEventListener('redraw', handleRedraw);

// Beim Beenden der Sitzung aufräumen
session.addEventListener('end', () => {
  cylinderLayer.onredraw = null;
  cylinderLayer.removeEventListener('redraw', handleRedraw);
});

Synthetisches Ereignis für Tests erzeugen

// Annahme: quadLayer ist eine gültige XRQuadLayer
quadLayer.addEventListener('redraw', (e) => {
  console.log(e instanceof XRLayerEvent, e.layer === quadLayer);
});

const testEvent = new XRLayerEvent('redraw', { layer: quadLayer });
quadLayer.dispatchEvent(testEvent);
true true

// Wichtig · Fallstricke

Kompatibilität: Die WebXR Layers API ist experimentell und wird praktisch nur von Chromium-basierten XR-Browsern unterstützt, vor allem vom Meta Quest Browser. Desktop-Firefox und Safari bieten sie nicht an. Prüfe die Unterstützung per Feature-Erkennung ('XRLayerEvent' in window, 'XRWebGLBinding' in window). Fordere das Feature beim Start der Sitzung als requiredFeatures bzw. optionalFeatures: ['layers'] an.

  • Zeichne im redraw-Handler nicht direkt. Setze dort nur eine Markierung, denn getSubImage() braucht einen gültigen XRFrame und funktioniert nur im requestAnimationFrame-Callback.
  • Zusätzlich zum Ereignis solltest du in jedem Frame layer.needsRedraw prüfen. Direkt nach dem Erzeugen ist die Eigenschaft true, ohne dass redraw ausgelöst wird.
  • XRProjectionLayer wird ohnehin in jedem Frame gezeichnet. redraw ist vor allem bei Kompositionsebenen mit statischem Inhalt wichtig.
  • Das Ereignis ist nur in sicheren Kontexten (HTTPS) verfügbar, da WebXR selbst einen sicheren Kontext voraussetzt.