Start · Sprachen · JavaScript · Referenz · XRSession.requestHitTestSource()

XRSession.requestHitTestSource()

Methode

Fordert eine <code>XRHitTestSource</code> an, mit der pro Frame Strahl-Treffer auf realen Oberflächen über <code>XRFrame.getHitTestResults()</code> ermittelt werden.

seit JavaScript WebXR Hit Test Module – Chrome/Edge 81+ (Android), Kategorie: webapi

Signatur

XRSession.prototype.requestHitTestSource(options)

Beschreibung

Die Methode requestHitTestSource() gehört zum WebXR Hit Test Module und ist die Grundlage für typische Augmented-Reality-Funktionen wie „Objekt auf dem Boden platzieren“. Sie gibt ein Promise zurück, das mit einem XRHitTestSource-Objekt erfüllt wird. Dieses Objekt beschreibt einen Strahl (Ray), der relativ zu einem Referenzraum definiert ist, etwa dem "viewer"-Raum (Blickrichtung der Kamera bzw. des Geräts).

Die Quelle übergibt man danach in jedem Animationsframe an XRFrame.getHitTestResults(). Dabei kommt ein Array von XRHitTestResult-Objekten heraus, die nach Entfernung sortiert sind. Über result.getPose(referenceSpace) erhält man Position und Ausrichtung des Treffers in der realen Welt, zum Beispiel für einen Platzierungs-Cursor (Reticle).

Voraussetzung ist eine "immersive-ar"-Sitzung, bei der das Feature "hit-test" in requiredFeatures oder optionalFeatures angefordert wurde. Die Quelle bleibt aktiv, bis man sie mit XRHitTestSource.cancel() beendet oder die Sitzung endet. Für Treffer bei flüchtigen Eingabequellen, etwa Bildschirm-Taps, gibt es die verwandte Methode requestHitTestSourceForTransientInput().

Parameter

Name Typ Default Beschreibung
$options Pflicht XRHitTestOptionsInit Konfigurationsobjekt mit folgenden Eigenschaften:
  • space (XRSpace, Pflicht): Der Raum, an den der Strahl gebunden ist, z. B. der "viewer"-Referenzraum oder inputSource.targetRaySpace.
  • entityTypes (Array<string>, optional): Welche Objektarten getroffen werden dürfen: "point", "plane", "mesh". Standard ist ["plane"].
  • offsetRay (XRRay, optional): Strahl relativ zu space. Standard ist ein Strahl vom Ursprung entlang der negativen Z-Achse.

Rückgabewert

Typ
Promise<XRHitTestSource>
Beschreibung
Ein Promise, das mit einem XRHitTestSource erfüllt wird. Es wird abgelehnt (NotSupportedError), wenn das Feature "hit-test" nicht aktiviert wurde, und mit InvalidStateError, wenn die Sitzung bereits beendet ist.

Beispiele

AR-Sitzung starten und Hit-Test-Quelle anfordern

const startAR = async () => {
  if (!(await navigator.xr?.isSessionSupported('immersive-ar'))) {
    console.log('AR wird nicht unterstützt');
    return;
  }

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

  const viewerSpace = await session.requestReferenceSpace('viewer');
  const hitTestSource = await session.requestHitTestSource({
    space: viewerSpace
  });

  console.log('Hit-Test-Quelle bereit:', hitTestSource);
  return { session, hitTestSource };
};

// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#ar-button').addEventListener('click', startAR);
Hit-Test-Quelle bereit: XRHitTestSource {}

Platzierungs-Cursor pro Frame aktualisieren

const runHitTestLoop = async (session, reticle) => {
  const localSpace = await session.requestReferenceSpace('local');
  const viewerSpace = await session.requestReferenceSpace('viewer');
  const hitTestSource = await session.requestHitTestSource({
    space: viewerSpace,
    entityTypes: ['plane', 'point']
  });

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

    const results = frame.getHitTestResults(hitTestSource);
    if (results.length > 0) {
      const pose = results[0].getPose(localSpace);
      reticle.visible = true;
      reticle.matrix = pose.transform.matrix; // Float32Array(16)
    } else {
      reticle.visible = false;
    }
  };

  session.requestAnimationFrame(onFrame);

  // Aufräumen beim Beenden der Sitzung
  session.addEventListener('end', () => hitTestSource.cancel());
};

Eigenen Strahl mit Versatz (offsetRay) verwenden

const requestAngledSource = async (session) => {
  const viewerSpace = await session.requestReferenceSpace('viewer');

  // Strahl leicht nach unten geneigt, damit der Boden eher getroffen wird
  const ray = new XRRay(
    { x: 0, y: 0, z: 0, w: 1 },
    { x: 0, y: -0.3, z: -1, w: 0 }
  );

  try {
    return await session.requestHitTestSource({
      space: viewerSpace,
      offsetRay: ray
    });
  } catch (err) {
    console.error(`Hit-Test nicht verfügbar: ${err.name}`);
    return null;
  }
};

// Wichtig · Fallstricke

  • Feature anfordern: Ohne "hit-test" in requiredFeatures/optionalFeatures bei navigator.xr.requestSession() wird das Promise mit NotSupportedError abgelehnt. Wurde das Feature nur optional angefordert, sollte man prüfen, ob die Methode existiert (typeof session.requestHitTestSource === 'function').
  • Browser-Kompatibilität: Unterstützt wird die Methode vor allem von Chromium-Browsern auf Android mit ARCore (Chrome, Edge, Samsung Internet) sowie teilweise von Meta Quest Browser. Firefox und Safari unterstützen sie nicht. Das Hit Test Module ist noch ein Entwurf (Working Draft).
  • Sicherer Kontext: WebXR steht nur über HTTPS bzw. localhost zur Verfügung. Eine immersive Sitzung braucht eine Nutzeraktion, und die Permissions-Policy xr-spatial-tracking muss erlaubt sein (wichtig bei iframes).
  • Ressourcen freigeben: Nicht mehr benötigte Quellen mit hitTestSource.cancel() beenden. Ein neuer Aufruf pro Frame ist falsch und verschwendet Leistung: Die Quelle wird einmal angelegt und dann wiederverwendet.
  • Leere Ergebnisse: Direkt nach dem Start liefert getHitTestResults() oft ein leeres Array, weil das Gerät die Umgebung erst erfassen muss. Die Oberfläche sollte daher einen Hinweis wie „Gerät langsam bewegen“ zeigen.