Signatur
Beschreibung
Die Eigenschaft transform von XRCylinderLayer enthält ein XRRigidTransform. Es gibt an, wo der Mittelpunkt des Zylinders liegt und wie er ausgerichtet ist, und zwar relativ zum Referenzraum, der in layer.space hinterlegt ist. Der Zylinder selbst wird durch radius, centralAngle und aspectRatio beschrieben. Der Betrachter befindet sich dabei normalerweise im Zentrum des Zylinders.
Die Eigenschaft lässt sich lesen und schreiben. Den Anfangswert übergibt man üblicherweise beim Erzeugen über XRWebGLBinding.createCylinderLayer() mit der Option transform. Wird dort nichts angegeben, ist der Wert eine Identitätstransformation, also ohne Versatz und ohne Drehung. Später weist man einfach ein neues XRRigidTransform zu, etwa um ein gebogenes Menü mit dem Kopf mitzubewegen oder es neu vor dem Nutzer zu platzieren.
Einsatzgebiete sind gekrümmte Bedienoberflächen, Videoflächen oder Textpanels in immersiven Sitzungen. Solche Ebenen werden direkt vom Compositor gezeichnet und wirken dadurch schärfer als Texturen, die man selbst in der WebGL-Szene rendert.
Rückgabewert
XRRigidTransform mit position (DOMPointReadOnly) und orientation (Quaternion als DOMPointReadOnly). Beide Angaben beziehen sich auf layer.space. Beim Setzen muss ebenfalls ein XRRigidTransform übergeben werden.Beispiele
Zylinder-Ebene mit Anfangsposition erzeugen
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['layers']
});
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const refSpace = await session.requestReferenceSpace('local');
const binding = new XRWebGLBinding(session, gl);
const cylinder = binding.createCylinderLayer({
space: refSpace,
viewPixelWidth: 1200,
viewPixelHeight: 600,
radius: 2,
centralAngle: Math.PI / 2,
aspectRatio: 2,
// 1,6 m Höhe, zentriert beim Nutzer
transform: new XRRigidTransform({ x: 0, y: 1.6, z: 0 })
});
session.updateRenderState({ layers: [cylinder] });
console.log(cylinder.transform.position.y);
Ebene nachträglich um 45° drehen
// Drehung um die Y-Achse als Quaternion
const winkel = Math.PI / 4;
const q = { x: 0, y: Math.sin(winkel / 2), z: 0, w: Math.cos(winkel / 2) };
cylinder.transform = new XRRigidTransform(
{ x: 0, y: 1.6, z: 0 },
q
);
const o = cylinder.transform.orientation;
console.log(o.y.toFixed(3), o.w.toFixed(3));
Menü an der aktuellen Blickrichtung ausrichten
const recenter = (frame) => {
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
const { position, orientation } = pose.transform;
// Nur die Drehung um die Hochachse übernehmen (Yaw)
const yaw = Math.atan2(
2 * (orientation.w * orientation.y + orientation.x * orientation.z),
1 - 2 * (orientation.y ** 2 + orientation.x ** 2)
);
cylinder.transform = new XRRigidTransform(
{ x: position.x, y: position.y, z: position.z },
{ x: 0, y: Math.sin(yaw / 2), z: 0, w: Math.cos(yaw / 2) }
);
};
session.addEventListener('select', (event) => recenter(event.frame));
// Wichtig · Fallstricke
- Kompatibilität: Die WebXR Layers API ist experimentell. Unterstützt wird sie vor allem im Meta Quest Browser und in einigen Chromium-Builds. Firefox und Safari unterstützen sie nicht. Das Feature
'layers'muss beirequestSession()angefordert werden. Wer Browser ohne Unterstützung abdecken will, prüft vorhertypeof XRWebGLBinding.prototype.createCylinderLayer === 'function'. - Das Objekt ist unveränderlich:
XRRigidTransformhat nur lesbare Eigenschaften.layer.transform.position.x = 1hat keine Wirkung. Man muss immer ein neuesXRRigidTransformzuweisen. - Bezugsraum beachten: Die Transformation bezieht sich auf
layer.space. Ist dieser Raum ein'viewer'-Raum, bewegt sich die Ebene mit dem Kopf mit. Bei'local'oder'local-floor'bleibt sie fest im Raum stehen. - Quaternionen normieren: Der Konstruktor normiert die Orientierung selbst. Eine Null-Quaternion führt aber zu einem Fehler.
- Nur Starrkörper-Transformation: Skalierung ist nicht möglich. Die Größe legt man über
radius,centralAngleundaspectRatiofest.