Start · Sprachen · JavaScript · Referenz · XRHitTestResult

XRHitTestResult

Schnittstelle

Ein einzelnes Ergebnis eines WebXR-Treffer-Tests, also ein Schnittpunkt eines Strahls mit einer realen Oberfläche, dessen Pose über <code>getPose()</code> abgefragt wird.

seit JavaScript WebXR Hit Test Module – Chromium-Browser (Chrome/E Kategorie: webapi

Signatur

interface XRHitTestResult

Beschreibung

XRHitTestResult gehört zum WebXR Hit Test Module. Dieses Modul ergänzt die WebXR Device API. Wenn ein Treffer-Test läuft, der über XRSession.requestHitTestSource() oder requestHitTestSourceForTransientInput() angelegt wurde, liefert jeder XRFrame eine Liste solcher Ergebnisse. Jedes Ergebnis steht für einen Punkt, an dem ein gedachter Strahl eine erkannte reale Oberfläche trifft, etwa einen Boden, einen Tisch oder eine Wand.

Das Interface hat keinen öffentlichen Konstruktor. Man bekommt Instanzen nur über XRFrame.getHitTestResults(hitTestSource), als Array. Bei vorübergehenden Eingaben wie Bildschirmberührungen kommen sie über XRTransientInputHitTestResult.results. Das Array ist nach Entfernung sortiert, der nächstgelegene Treffer steht an erster Stelle.

Die wichtigsten Methoden:

  • getPose(baseSpace): liefert eine XRPose (Position und Ausrichtung des Treffers) relativ zum angegebenen XRSpace. Die Orientierung zeigt mit der Y-Achse entlang der Oberflächennormalen.
  • createAnchor(): erzeugt einen XRAnchor am Trefferpunkt, sofern das Anchors-Modul unterstützt wird. Das Ergebnis ist ein Promise<XRAnchor>.

Typischer Einsatz sind Augmented-Reality-Anwendungen: ein Zielkreuz (Reticle) auf dem Boden anzeigen, virtuelle Möbel auf erkannte Flächen stellen oder Objekte per Tippen platzieren.

Parameter

Name Typ Default Beschreibung
$baseSpace Pflicht XRSpace Parameter von getPose(): Referenzraum, relativ zu dem die Pose des Treffers berechnet wird, meist der XRReferenceSpace vom Typ 'local' oder 'local-floor'.

Rückgabewert

Typ
XRPose | null
Beschreibung
getPose(baseSpace) gibt eine XRPose mit transform (Position und Ausrichtung) zurück, oder null, wenn sich die Pose relativ zu baseSpace nicht bestimmen lässt. createAnchor() gibt ein Promise<XRAnchor> zurück.

Beispiele

AR-Sitzung mit Treffer-Test starten und Ergebnisse lesen

const startAR = async () => {
  const session = await navigator.xr.requestSession('immersive-ar', {
    requiredFeatures: ['hit-test', 'local']
  });

  const viewerSpace = await session.requestReferenceSpace('viewer');
  const localSpace = await session.requestReferenceSpace('local');

  // Strahl geht von der Blickrichtung des Geräts aus
  const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });

  const onFrame = (time, frame) => {
    session.requestAnimationFrame(onFrame);
    const results = frame.getHitTestResults(hitTestSource);

    if (results.length > 0) {
      const hit = results[0]; // XRHitTestResult, nächster Treffer
      const pose = hit.getPose(localSpace);
      if (pose) {
        const { x, y, z } = pose.transform.position;
        console.log(`Treffer bei x=${x.toFixed(2)} y=${y.toFixed(2)} z=${z.toFixed(2)}`);
      }
    }
  };

  session.requestAnimationFrame(onFrame);
};

document.querySelector('#ar-button').addEventListener('click', startAR);
Treffer bei x=0.12 y=-1.43 z=-0.87

Zielkreuz (Reticle) an der Trefferpose ausrichten

// reticle: ein 3D-Objekt (z. B. aus three.js) mit matrix-Eigenschaft
const updateReticle = (frame, hitTestSource, refSpace, reticle) => {
  const [hit] = frame.getHitTestResults(hitTestSource);
  if (!hit) {
    reticle.visible = false;
    return;
  }
  const pose = hit.getPose(refSpace);
  reticle.visible = pose !== null;
  if (pose) {
    // 4x4-Matrix (Float32Array) direkt übernehmen
    reticle.matrix.fromArray(pose.transform.matrix);
  }
};

Objekt per Tippen verankern mit createAnchor()

const anchors = new Set();

const setupTapToPlace = async (session, refSpace) => {
  const transientSource = await session.requestHitTestSourceForTransientInput({
    profile: 'generic-touchscreen'
  });

  let lastHit = null;

  const onFrame = (time, frame) => {
    session.requestAnimationFrame(onFrame);
    const inputResults = frame.getHitTestResultsForTransientInput(transientSource);
    for (const input of inputResults) {
      if (input.results.length > 0) lastHit = input.results[0];
    }
  };
  session.requestAnimationFrame(onFrame);

  session.addEventListener('select', async () => {
    if (!lastHit?.createAnchor) return; // Anchors-Modul nicht verfügbar
    try {
      const anchor = await lastHit.createAnchor();
      anchors.add(anchor);
      console.log('Anker erstellt, Anzahl:', anchors.size);
    } catch (err) {
      console.error('Anker fehlgeschlagen:', err);
    }
  });
};
Anker erstellt, Anzahl: 1

// Wichtig · Fallstricke

  • Kompatibilität: Treffer-Tests und AR-Sitzungen werden praktisch nur von Chromium-Browsern unterstützt, vor allem Chrome für Android mit ARCore. Firefox und Safari auf dem Desktop kennen die Schnittstelle nicht. Vor der Nutzung mit navigator.xr?.isSessionSupported('immersive-ar') prüfen.
  • Sicherer Kontext: WebXR funktioniert nur über HTTPS (oder localhost). Eine immersive Sitzung braucht eine Benutzeraktion, zum Beispiel einen Klick.
  • Feature anfordern: 'hit-test' muss in requiredFeatures oder optionalFeatures von requestSession() stehen. Sonst schlägt requestHitTestSource() fehl.
  • Nur im aktuellen Frame gültig: Ein XRHitTestResult gehört zu dem XRFrame, in dem es entstanden ist. getPose() außerhalb des Frame-Callbacks löst einen InvalidStateError aus. Deshalb die Pose-Daten kopieren, nicht das Ergebnisobjekt aufheben. Eine Ausnahme ist createAnchor(), das man im zugehörigen select-Ereignis aufrufen kann, wenn der Treffer frisch ist.
  • Leere Ergebnisse: Solange das Gerät noch keine Flächen erkannt hat, ist das Array leer. getPose() kann außerdem null liefern. Beide Fälle immer abfangen.
  • Ressourcen freigeben: Nicht mehr benötigte Quellen mit hitTestSource.cancel() beenden. Das spart Rechenleistung und Akku.
  • createAnchor() gibt es nur, wenn das WebXR Anchors Module unterstützt und das Feature 'anchors' angefordert wurde.