Start · Sprachen · JavaScript · Referenz · XRInputSource.gripSpace

XRInputSource.gripSpace

Eigenschaft

Liefert ein <code>XRSpace</code>, dessen Ursprung der Pose der greifenden Hand bzw. des Controllers folgt, oder <code>null</code>, wenn das Eingabegerät nicht gehalten werden kann.

seit JavaScript WebXR Device API – Chromium-Browser (Chrome/Edge 7 Kategorie: webapi

Signatur

XRInputSource.gripSpace

Beschreibung

Die schreibgeschützte Eigenschaft gripSpace eines XRInputSource-Objekts gibt ein XRSpace zurück, dessen Ursprung und Ausrichtung der Handfläche bzw. dem Griff eines Controllers folgen. Mit diesem Raum rendert man virtuelle Objekte so, als würde der Nutzer sie in der Hand halten, zum Beispiel ein Controller-Modell, ein Schwert, eine Taschenlampe oder ein Werkzeug.

Laut Spezifikation liegt der Ursprung in der Mitte der geschlossenen Faust. Die −Z-Achse zeigt dabei nach vorn durch die Faust, also in die Richtung, in die ein gehaltener Stab zeigen würde. Die +X-Achse steht senkrecht zum Handrücken, bei der rechten Hand zeigt sie also nach außen und bei der linken Hand nach innen. Die +Y-Achse zeigt nach oben, grob in Richtung Daumen. Damit unterscheidet sich gripSpace von targetRaySpace: Dieser beschreibt den Zielstrahl zum Auswählen und Zeigen, gripSpace dagegen die Lage der Hand.

Für die konkrete Pose übergibt man den Raum in jedem Frame an XRFrame.getPose(space, baseSpace), meist zusammen mit dem Referenzraum der Sitzung. Der Rückgabewert ist ein XRPose mit einer transform-Matrix, oder null, wenn das Tracking gerade verloren ist.

Bei Eingabequellen, die man nicht halten kann, ist die Eigenschaft null. Das betrifft blickgesteuerte Eingaben (targetRayMode === "gaze") und Bildschirm-Tippen ("screen") auf Smartphones.

Rückgabewert

Typ
XRSpace | null
Beschreibung
Ein XRSpace, der die Griffpose der Eingabequelle beschreibt, oder null, wenn das Gerät nicht gehalten werden kann (z. B. bei Blick- oder Bildschirmeingabe).

Beispiele

Controller-Modell in der Hand rendern

const session = await navigator.xr.requestSession('immersive-vr');
const refSpace = await session.requestReferenceSpace('local-floor');

const onXRFrame = (time, frame) => {
  session.requestAnimationFrame(onXRFrame);

  for (const source of session.inputSources) {
    // Blick- oder Bildschirmeingaben haben keinen gripSpace
    if (!source.gripSpace) continue;

    const pose = frame.getPose(source.gripSpace, refSpace);
    if (pose) {
      // 4x4-Matrix (Float32Array) für die Render-Engine
      drawControllerModel(source.handedness, pose.transform.matrix);
    }
  }
};

session.requestAnimationFrame(onXRFrame);

Griffposition und Zielstrahl vergleichen

const logInputPoses = (frame, refSpace) => {
  for (const source of frame.session.inputSources) {
    const grip = source.gripSpace
      ? frame.getPose(source.gripSpace, refSpace)
      : null;
    const ray = frame.getPose(source.targetRaySpace, refSpace);

    if (grip && ray) {
      const { x, y, z } = grip.transform.position;
      console.log(`${source.handedness}: Griff bei (${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)})`);
      console.log('Strahl-Ursprung:', ray.transform.position);
    }
  }
};
right: Griff bei (0.21, 1.05, -0.32) Strahl-Ursprung: DOMPointReadOnly {x: 0.22, y: 1.07, z: -0.36, w: 1}

Neue Eingabequellen auf gripSpace prüfen

session.addEventListener('inputsourceschange', (event) => {
  for (const source of event.added) {
    const holdable = source.gripSpace !== null;
    console.log(`${source.targetRayMode} (${source.handedness}) – greifbar: ${holdable}`);
  }
});
tracked-pointer (left) – greifbar: true tracked-pointer (right) – greifbar: true

// Wichtig · Fallstricke

  • Immer auf null prüfen: Bei targetRayMode "gaze" und "screen" (AR auf dem Smartphone) gibt es keinen gripSpace. Ein ungeprüfter Aufruf von frame.getPose(null, …) wirft einen TypeError.
  • Pose kann null sein: Auch wenn ein gripSpace vorhanden ist, liefert getPose() null, sobald das Tracking abreißt, etwa wenn der Controller außer Sicht ist. Modelle sollte man dann ausblenden oder an der letzten bekannten Position einfrieren.
  • Nicht mit targetRaySpace verwechseln: Für Zeigestrahlen und Treffertests nutzt man targetRaySpace, für gehaltene Objekte gripSpace. Beide Räume können deutlich gegeneinander verschoben und gedreht sein.
  • Handtracking: Bei optisch verfolgten Händen (source.hand) wird gripSpace aus den Gelenkdaten abgeleitet. Für genaue Fingerposen nutzt man XRHand mit frame.getJointPose().
  • Nur in jedem Frame gültig: Posen immer innerhalb des requestAnimationFrame-Callbacks der XRSession abfragen. Ein außerhalb davon verwendetes XRFrame ist ungültig und wirft einen Fehler.
  • Kompatibilität: WebXR braucht einen sicheren Kontext (HTTPS). Unterstützt wird es vor allem in Chromium-Browsern und im Meta Quest Browser. Firefox (Desktop) und Safari (macOS) unterstützen WebXR nicht. Vorher mit navigator.xr?.isSessionSupported() prüfen.