Signatur
Beschreibung
Die Eigenschaft XRLayerEvent.layer ist schreibgeschützt. Sie liefert die Ebene (XRLayer), von der ein Ereignis der WebXR Layers API stammt. Praktisch betrifft das vor allem das redraw-Ereignis. Kompositionsebenen wie XRQuadLayer, XRCylinderLayer, XREquirectLayer und XRCubeLayer lösen es aus, wenn der Browser ihren Inhalt verworfen hat und die Anwendung ihn neu zeichnen muss.
Nützlich ist die Eigenschaft vor allem, wenn ein einziger Ereignis-Handler für mehrere Ebenen zuständig ist. Das ist zum Beispiel der Fall bei mehreren schwebenden UI-Panels als Quad-Ebenen. Über event.layer erkennt der Handler, welche Ebene neu gezeichnet werden muss. Er braucht dafür keine eigene Closure pro Ebene.
Wichtig: Das redraw-Ereignis ist nur ein Signal. Gezeichnet wird nicht im Ereignis-Handler. Das geschieht erst im nächsten Rückruf von XRSession.requestAnimationFrame(), denn nur dort gibt es ein gültiges XRFrame. Mit diesem Frame holt man über XRWebGLBinding.getSubImage() die Zieltextur. Üblich ist deshalb folgendes Vorgehen: Im Handler wird die Ebene aus event.layer vorgemerkt, und im Frame-Rückruf wird sie dann neu gerendert.
Rückgabewert
XRCompositionLayer, etwa XRQuadLayer oder XRCylinderLayer. Der Wert wird beim Erzeugen des Ereignisses festgelegt und lässt sich danach nicht mehr ändern.Beispiele
redraw-Ereignis mit addEventListener und event.layer auswerten
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['layers']
});
const binding = new XRWebGLBinding(session, gl);
const refSpace = await session.requestReferenceSpace('local');
const menuLayer = binding.createQuadLayer({
space: refSpace,
viewPixelWidth: 1024,
viewPixelHeight: 512,
layout: 'mono',
width: 1.0,
height: 0.5
});
const projectionLayer = binding.createProjectionLayer();
session.updateRenderState({ layers: [projectionLayer, menuLayer] });
menuLayer.addEventListener('redraw', (event) => {
// event.layer ist dieselbe Instanz wie menuLayer
console.log(event.layer === menuLayer);
console.log(event.layer.needsRedraw);
});
Ein Handler für mehrere Ebenen: Neuzeichnen im nächsten Frame
// Voraussetzung: session, binding und refSpace wie im ersten Beispiel
const panels = ['links', 'rechts'].map((name, i) => {
const layer = binding.createQuadLayer({
space: refSpace,
viewPixelWidth: 512,
viewPixelHeight: 512,
layout: 'mono',
transform: new XRRigidTransform({ x: i === 0 ? -0.8 : 0.8, y: 1.5, z: -2 })
});
layer.name = name; // eigene Markierung
return layer;
});
const dirty = new Set();
const onRedraw = (event) => {
// Nur vormerken, nicht hier zeichnen
dirty.add(event.layer);
console.log(`Panel "${event.layer.name}" muss neu gezeichnet werden`);
};
panels.forEach((layer) => layer.addEventListener('redraw', onRedraw));
const onFrame = (time, frame) => {
for (const layer of dirty) {
const sub = binding.getSubImage(layer, frame);
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, sub.colorTexture, 0);
drawPanel(layer.name); // eigene Render-Funktion
}
dirty.clear();
frame.session.requestAnimationFrame(onFrame);
};
session.requestAnimationFrame(onFrame);
Alternative über die onredraw-Eigenschaft
// Nur ein Handler pro Ebene möglich – eine neue Zuweisung ersetzt den alten
menuLayer.onredraw = ({ layer }) => {
console.log(layer.constructor.name);
needsMenuRedraw = true;
};
// Handler wieder entfernen
menuLayer.onredraw = null;
// Wichtig · Fallstricke
- Experimentell: Die WebXR Layers API ist noch nicht in allen Browsern verfügbar. Am besten unterstützt wird sie derzeit im Meta Quest Browser. Desktop-Firefox und Safari unterstützen sie nicht. Damit Ebenen überhaupt entstehen, muss die Sitzung mit
requiredFeaturesoderoptionalFeatures: ['layers']angefordert werden. Außerdem ist ein sicherer Kontext (HTTPS) nötig. - Nicht im Handler zeichnen:
getSubImage()braucht ein gültigesXRFrame. Imredraw-Handler gibt es keins. Merken Sie sichevent.layerdeshalb vor und zeichnen Sie die Ebene im nächstenrequestAnimationFrame-Rückruf. - Schreibgeschützt: Eine Zuweisung an
event.layerwird im nicht-strikten Modus stillschweigend ignoriert und löst im strikten Modus einenTypeErroraus. - Der Konstruktor
new XRLayerEvent(type, { layer })verlangt eine echteXRLayer-Instanz. Für Unit-Tests ohne XR-Gerät müssen Sie deshalb Mocks oder den WebXR-Emulator verwenden. - Referenzen auf Ebenen aus beendeten Sitzungen sollten Sie verwerfen, zum Beispiel in einem
Setvorgemerkter Ebenen. Andernfalls entstehen Speicherlecks. NachXRSession.end()oderlayer.destroy()ist die Ebene nicht mehr verwendbar.