Signatur
Beschreibung
XRJointPose.radius gibt eine Gleitkommazahl in Metern zurück. Sie beschreibt, wie weit die Hautoberfläche vom Mittelpunkt eines bestimmten Handgelenks entfernt ist. Jedes Gelenk aus dem XRHand-Objekt, etwa "index-finger-tip" oder "wrist", lässt sich so als Kugel darstellen: Mittelpunkt ist transform.position, der Radius ist radius.
Die Eigenschaft wird vor allem für Rendering und Kollisionserkennung gebraucht. Damit kannst du Fingerkuppen als passend große Kugeln zeichnen, Berührungen mit virtuellen Knöpfen erkennen („Poke“-Interaktion) oder den Pinch-Abstand zwischen Daumen und Zeigefinger ohne die Hautdicke berechnen.
Ein XRJointPose bekommst du pro Frame über XRFrame.getJointPose(joint, baseSpace). Mit XRFrame.fillJointRadii() holst du alle Gelenke auf einmal in ein Float32Array. Der Wert gilt immer nur für den aktuellen Frame und kann sich ändern, weil die Laufzeitumgebung die Handgeometrie laufend schätzt.
Rückgabewert
Beispiele
Radius der Zeigefingerkuppe pro Frame auslesen
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['hand-tracking']
});
const refSpace = await session.requestReferenceSpace('local-floor');
const onFrame = (time, frame) => {
for (const source of session.inputSources) {
if (!source.hand) continue;
const tip = source.hand.get('index-finger-tip');
const pose = frame.getJointPose(tip, refSpace);
if (pose) {
console.log(`${source.handedness}: ${(pose.radius * 1000).toFixed(1)} mm`);
}
}
session.requestAnimationFrame(onFrame);
};
session.requestAnimationFrame(onFrame);
Pinch-Geste unter Berücksichtigung der Hautdicke erkennen
const isPinching = (frame, hand, refSpace) => {
const thumb = frame.getJointPose(hand.get('thumb-tip'), refSpace);
const index = frame.getJointPose(hand.get('index-finger-tip'), refSpace);
if (!thumb || !index) return false;
const a = thumb.transform.position;
const b = index.transform.position;
const dist = Math.hypot(a.x - b.x, a.y - b.y, a.z - b.z);
// Abstand zwischen den Hautoberflächen statt zwischen den Gelenkmittelpunkten
const surfaceGap = dist - thumb.radius - index.radius;
return surfaceGap < 0.005; // weniger als 5 mm
};
Fingerkuppe mit virtuellem Knopf kollidieren lassen
const button = { x: 0, y: 1.2, z: -0.4, radius: 0.02 };
const touchesButton = (jointPose) => {
const p = jointPose.transform.position;
const dist = Math.hypot(p.x - button.x, p.y - button.y, p.z - button.z);
return dist <= button.radius + jointPose.radius;
};
// in der Frame-Schleife:
// const pose = frame.getJointPose(hand.get('index-finger-tip'), refSpace);
// if (pose && touchesButton(pose)) console.log('Knopf gedrückt');
// Wichtig · Fallstricke
- Einheit: Der Wert ist in Metern angegeben, nicht in Zentimetern oder Millimetern. Typische Werte für Fingerkuppen liegen bei etwa 0,005–0,01.
- Kann fehlen:
frame.getJointPose()gibtnullzurück, wenn die Hand gerade nicht erfasst wird. Prüfe das immer, bevor du aufradiuszugreifst. - Nur mit Feature-Anfrage: Handgelenke gibt es nur, wenn die Sitzung mit
'hand-tracking'inrequiredFeaturesoderoptionalFeaturesgestartet wurde. - Performance: Wenn du viele Gelenke pro Frame brauchst, ist
XRFrame.fillJointRadii()zusammen mitfillPoses()effizienter als einzelnegetJointPose()-Aufrufe. - Kompatibilität: Die Eigenschaft ist nur in einem sicheren Kontext (HTTPS) verfügbar und wird derzeit hauptsächlich von Chromium-basierten XR-Browsern unterstützt, etwa dem Meta Quest Browser. Safari und Firefox bieten sie auf dem Desktop nicht an, Apple Vision Pro nur eingeschränkt.
- Datenschutz: Handgeometrie kann zum Identifizieren von Personen (Fingerprinting) genutzt werden. Deshalb können Browser die Werte runden oder vereinheitlichen.