Signatur
interface XRHitTestSource
Beschreibung
Wird von
XRSession.requestHitTestSource() als Promise<XRHitTestSource> geliefert. cancel() gibt undefined zurück.Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options.space Pflicht | XRSpace | Referenzraum, von dem der Strahl ausgeht, oft await session.requestReferenceSpace('viewer'). Gehört zu requestHitTestSource(options). |
|
| $options.offsetRay | XRRay | new XRRay() | Strahl relativ zu space. Ohne Angabe beginnt er im Ursprung und zeigt in Richtung -Z, also nach vorne. |
| $options.entityTypes | Array<'point'|'plane'|'mesh'> | ['plane'] | Arten von Umgebungsmerkmalen, die der Hit-Test berücksichtigen soll. |
Beispiele
Hit-Test-Quelle anfordern (AR-Sitzung starten)
const startAR = async () => {
if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-ar'))) {
console.log('AR wird nicht unterstützt');
return;
}
// Muss durch eine Nutzeraktion ausgelöst werden (z. B. Button-Klick)
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['hit-test', 'local']
});
const viewerSpace = await session.requestReferenceSpace('viewer');
const localSpace = await session.requestReferenceSpace('local');
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
console.log(hitTestSource instanceof XRHitTestSource);
return { session, hitTestSource, localSpace };
};
document.querySelector('#ar-button').addEventListener('click', startAR);
true
Ergebnisse pro Frame auswerten (Reticle positionieren)
const runLoop = ({ session, hitTestSource, localSpace }, reticle) => {
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)
const { x, y, z } = pose.transform.position;
console.log(`Treffer bei ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
} else {
reticle.visible = false;
}
};
session.requestAnimationFrame(onFrame);
};
Treffer bei 0.12, -1.35, -0.87
Eigener Strahl mit offsetRay und Aufräumen per cancel()
const setupDownwardHitTest = async (session) => {
const viewerSpace = await session.requestReferenceSpace('viewer');
// Strahl schräg nach unten-vorne
const ray = new XRRay({ x: 0, y: 0, z: 0 }, { x: 0, y: -0.5, z: -1 });
const source = await session.requestHitTestSource({
space: viewerSpace,
offsetRay: ray,
entityTypes: ['plane', 'point']
});
session.addEventListener('end', () => {
source.cancel(); // Abonnement freigeben
console.log('Hit-Test-Quelle beendet');
});
return source;
};
Hit-Test-Quelle beendet
// Wichtig · Fallstricke
- Feature-Anforderung:
'hit-test'muss beim Aufruf vonrequestSession()inrequiredFeaturesoderoptionalFeaturesstehen. Sonst schlägtrequestHitTestSource()mit einemNotSupportedErrorfehl. - Nur sichere Kontexte: WebXR funktioniert nur über HTTPS. Die Sitzung braucht eine Nutzeraktion. In iframes ist zusätzlich eine Permissions-Policy
xr-spatial-trackingnötig. - Browser-Unterstützung: Chromium-Browser auf Android mit ARCore unterstützen die API, ebenso einige Headsets wie Meta Quest Browser. Firefox und Safari auf iOS unterstützen sie nicht. Prüfe deshalb vorher mit
isSessionSupported('immersive-ar'). - Leere Ergebnisse: Direkt nach dem Start hat das Gerät oft noch keine Flächen erkannt.
getHitTestResults()gibt dann ein leeres Array zurück. Rechne damit und blende das Reticle aus. - Ressourcen: Beende nicht mehr benötigte Quellen mit
cancel(). Nachcancel()oder dem Ende der Sitzung darf die Quelle nicht mehr angetHitTestResults()übergeben werden, sonst wird einInvalidStateErrorgeworfen. - Datenschutz: Hit-Tests verraten etwas über die Geometrie der Umgebung. Browser verlangen deshalb eine Zustimmung des Nutzers.