Start · Sprachen · JavaScript · Referenz · XRTransientInputHitTestSource

XRTransientInputHitTestSource

Schnittstelle

Verwaltet ein Hittest-Abonnement für flüchtige Eingabequellen wie Bildschirm-Taps in AR-Sitzungen und liefert pro Frame die Treffer über <code>XRFrame.getHitTestResultsForTransientInput()</code>.

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

Signatur

interface XRTransientInputHitTestSource

Beschreibung

XRTransientInputHitTestSource gehört zum WebXR Hit Test Module. Das Interface steht für ein Abonnement, mit dem man Hittests für flüchtige Eingabequellen ausführt. Flüchtig heißt: Die Eingabequelle gibt es nur, solange die Interaktion läuft. Typisch ist ein Fingertipp auf den Bildschirm in einer Handheld-AR-Sitzung (targetRayMode === "screen"). Anders als bei einem Controller gibt es vorher kein XRInputSource-Objekt, an das man einen Hittest hängen könnte.

Eine Instanz erzeugt man nicht mit einem Konstruktor, sondern über XRSession.requestHitTestSourceForTransientInput(). Dabei gibt man ein Profil an, zum Beispiel "generic-touchscreen". So legt man fest, für welche Art von Eingabequelle das Abonnement gilt. In jedem Frame liefert dann XRFrame.getHitTestResultsForTransientInput(source) ein Array von XRTransientInputHitTestResult-Objekten zurück, eines pro gerade aktiver passender Eingabequelle. Jedes dieser Objekte enthält die Eingabequelle (inputSource) und die zugehörigen Treffer (results).

Das Interface hat nur eine Methode: cancel(). Sie beendet das Abonnement und gibt Ressourcen auf dem Gerät frei. Einsatzgebiet sind AR-Anwendungen, in denen Nutzer durch Tippen auf eine erkannte Fläche virtuelle Objekte platzieren, etwa Möbel, Marker oder Messpunkte.

Parameter

Name Typ Default Beschreibung
$cancel() method Beendet das Hittest-Abonnement. Danach liefert getHitTestResultsForTransientInput() für diese Quelle keine Treffer mehr. Rückgabewert: undefined.

Rückgabewert

Typ
XRTransientInputHitTestSource
Beschreibung
Wird von XRSession.requestHitTestSourceForTransientInput() als erfüllter Wert eines Promise zurückgegeben.

Beispiele

Abonnement für Bildschirm-Taps anlegen

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']
  });

  // Hittest-Quelle für flüchtige Touch-Eingaben anfordern
  const transientSource = await session.requestHitTestSourceForTransientInput({
    profile: 'generic-touchscreen'
  });
  console.log(transientSource instanceof XRTransientInputHitTestSource);
  return { session, transientSource };
};

// Muss aus einer Nutzergeste heraus aufgerufen werden
document.querySelector('#ar-button').addEventListener('click', startAR);
true

Treffer pro Frame auswerten und Objekt platzieren

const setupPlacement = async (session) => {
  const refSpace = await session.requestReferenceSpace('local');
  const hitSource = await session.requestHitTestSourceForTransientInput({
    profile: 'generic-touchscreen'
  });

  let lastHitPose = null;

  const onFrame = (time, frame) => {
    const perInput = frame.getHitTestResultsForTransientInput(hitSource);
    for (const { inputSource, results } of perInput) {
      if (results.length > 0) {
        const pose = results[0].getPose(refSpace);
        lastHitPose = pose.transform;
        console.log('Treffer bei', pose.transform.position, 'über', inputSource.targetRayMode);
      }
    }
    session.requestAnimationFrame(onFrame);
  };
  session.requestAnimationFrame(onFrame);

  // Beim Loslassen des Fingers Objekt an letzter Trefferstelle platzieren
  session.addEventListener('select', () => {
    if (lastHitPose) console.log('Objekt platziert bei', lastHitPose.position);
  });

  return hitSource;
};
Treffer bei DOMPointReadOnly {x: 0.12, y: -1.3, z: -0.8, w: 1} über screen

Abonnement sauber beenden

const stopPlacement = (session, hitSource) => {
  hitSource.cancel(); // Ressourcen freigeben
  console.log('Hittest-Abonnement beendet');
};

// Alternativ automatisch beim Sitzungsende
// session.addEventListener('end', () => hitSource.cancel());
Hittest-Abonnement beendet

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Unterstützt wird die API nur in Chromium-basierten Browsern auf Android mit ARCore (Chrome, Edge, Samsung Internet) und in einigen XR-Browsern. Firefox und Safari (iOS) bieten sie nicht an. Vorher mit navigator.xr.isSessionSupported('immersive-ar') und 'requestHitTestSourceForTransientInput' in XRSession.prototype prüfen.
  • Das Feature "hit-test" muss bei requestSession() in requiredFeatures oder optionalFeatures stehen, sonst wird das Promise mit einem Fehler abgelehnt.
  • WebXR funktioniert nur in einem sicheren Kontext (HTTPS). Die Sitzung muss aus einer Nutzergeste heraus gestartet werden.
  • Bei getHitTestResultsForTransientInput() kann das Array leer sein: Solange niemand den Bildschirm berührt, gibt es keine flüchtige Eingabequelle.
  • Das Profil muss zur Eingabequelle passen, zum Beispiel "generic-touchscreen". Bei einem falschen Profil kommen keine Treffer.
  • cancel() aufrufen, wenn man keine Hittests mehr braucht. Hittests kosten Rechenleistung. Nach dem Ende der Sitzung ist die Quelle ohnehin ungültig.
  • Die Spezifikation hat noch Entwurfsstatus. Details können sich ändern.