Start · Sprachen · JavaScript · Referenz · XRTransientInputHitTestResult

XRTransientInputHitTestResult

Schnittstelle

Enthält die Hit-Test-Ergebnisse eines Frames für <strong>eine</strong> transiente Eingabequelle (z. B. einen Bildschirm-Tipp), bestehend aus <code>inputSource</code> und <code>results</code>.

seit JavaScript Experimentell: Chrome/Edge 81+ (Android, ARCore), Kategorie: webapi

Signatur

interface XRTransientInputHitTestResult

Beschreibung

Das Interface XRTransientInputHitTestResult gehört zum WebXR Hit Test Module. Es fasst die Ergebnisse eines Hit-Tests für transiente Eingaben zusammen. Transiente Eingaben sind Eingabequellen, die nur kurz existieren, etwa ein Finger-Tipp auf dem Touchscreen eines Smartphones in einer AR-Sitzung (Profil "generic-touchscreen"). Weil diese Quellen beim Anfordern des Hit-Tests noch gar nicht existieren, wird der Hit-Test über ein Profil statt über eine konkrete Quelle registriert.

Instanzen werden nie direkt erzeugt. Man erhält sie in jedem Frame als Array über XRFrame.getHitTestResultsForTransientInput(hitTestSource), wobei hitTestSource eine XRTransientInputHitTestSource ist, die zuvor mit XRSession.requestHitTestSourceForTransientInput() angefordert wurde. Für jede aktuell aktive transiente Eingabequelle liefert das Array genau ein XRTransientInputHitTestResult.

Das Interface besitzt zwei schreibgeschützte Eigenschaften:

  • inputSource – die XRInputSource, zu der die Ergebnisse gehören (z. B. der aktuelle Finger).
  • results – ein eingefrorenes Array von XRHitTestResult-Objekten, sortiert nach Entfernung (nächster Treffer zuerst). Mit XRHitTestResult.getPose(referenceSpace) erhält man daraus Position und Ausrichtung des Treffers auf einer realen Oberfläche.

Typischer Einsatz: Nutzer tippt auf den Bildschirm, und an der Stelle, an der der „Strahl“ des Tipps eine erkannte Ebene (Boden, Tisch) trifft, wird ein virtuelles Objekt platziert oder ein Fadenkreuz angezeigt.

Rückgabewert

Typ
XRTransientInputHitTestResult
Beschreibung
Wird nicht konstruiert, sondern als Element des Arrays von XRFrame.getHitTestResultsForTransientInput() geliefert. Eigenschaften: inputSource (XRInputSource) und results (FrozenArray<XRHitTestResult>).

Beispiele

AR-Sitzung starten und transiente Hit-Test-Quelle anfordern

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

  // 'hit-test' muss als Feature angefordert werden
  const session = await navigator.xr.requestSession('immersive-ar', {
    requiredFeatures: ['hit-test', 'local-floor']
  });

  const refSpace = await session.requestReferenceSpace('local-floor');

  // Hit-Test für alle künftigen Touchscreen-Tipps registrieren
  const transientSource = await session.requestHitTestSourceForTransientInput({
    profile: 'generic-touchscreen'
  });

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

// Muss aus einer Nutzer-Geste heraus aufgerufen werden
document.querySelector('#ar-button').addEventListener('click', startAR);
Transiente Hit-Test-Quelle bereit: XRTransientInputHitTestSource {}

Ergebnisse pro Frame auswerten

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

  // Array von XRTransientInputHitTestResult – eines pro aktivem Finger
  const perInput = frame.getHitTestResultsForTransientInput(transientSource);

  for (const inputResult of perInput) {
    const { inputSource, results } = inputResult;
    if (results.length === 0) continue;

    // Nächster Treffer steht an erster Stelle
    const pose = results[0].getPose(refSpace);
    if (!pose) continue;

    const { x, y, z } = pose.transform.position;
    console.log(`${inputSource.profiles[0]} trifft bei`, x.toFixed(2), y.toFixed(2), z.toFixed(2));
  }
};

session.requestAnimationFrame(onXRFrame);
generic-touchscreen trifft bei 0.12 0.00 -0.85

Objekt beim Tipp platzieren (select-Event) und Quelle aufräumen

let lastHitPose = null;

const onXRFrame = (time, frame) => {
  frame.session.requestAnimationFrame(onXRFrame);
  const perInput = frame.getHitTestResultsForTransientInput(transientSource);
  lastHitPose = perInput[0]?.results[0]?.getPose(refSpace) ?? null;
};

const onSelect = () => {
  if (!lastHitPose) return;
  // Hier z. B. ein 3D-Modell an lastHitPose.transform setzen
  console.log('Objekt platziert:', lastHitPose.transform.position);
};

session.addEventListener('select', onSelect);
session.requestAnimationFrame(onXRFrame);

session.addEventListener('end', () => {
  session.removeEventListener('select', onSelect);
  transientSource.cancel(); // Ressourcen freigeben
});
Objekt platziert: DOMPointReadOnly {x: 0.12, y: 0, z: -0.85, w: 1}

// Wichtig · Fallstricke

  • Experimentell: Nur in Chromium-basierten Browsern auf Android mit ARCore verfügbar; Firefox und Safari unterstützen das Hit Test Module nicht. Immer per Feature-Erkennung (navigator.xr, isSessionSupported(), 'requestHitTestSourceForTransientInput' in session) absichern.
  • Nur in sicheren Kontexten (HTTPS) und nur, wenn 'hit-test' in requiredFeatures bzw. optionalFeatures angefordert wurde – sonst wird das Promise mit NotSupportedError abgelehnt.
  • Das Array von getHitTestResultsForTransientInput() ist leer, solange kein Finger den Bildschirm berührt. Auch results kann leer sein, wenn keine Oberfläche erkannt wurde – immer auf Länge prüfen.
  • getPose() kann null liefern, wenn die Pose im gewählten Referenzraum nicht bestimmbar ist.
  • Ergebnisse gelten nur für den aktuellen Frame; Objekte nicht über Frames hinweg zwischenspeichern, sondern die Pose kopieren. Für dauerhaft stabile Positionen besser XRHitTestResult.createAnchor() nutzen.
  • Nicht mehr benötigte Quellen mit XRTransientInputHitTestSource.cancel() freigeben, um Rechenleistung zu sparen.