Signatur
Beschreibung
Mit requestHitTestSourceForTransientInput() legt eine immersive AR-Sitzung eine Hit-Test-Quelle an, die nicht an einen festen Referenzraum gebunden ist. Sie ist an kurzlebige (transiente) Eingabequellen gebunden. Ein typisches Beispiel ist das Antippen des Bildschirms auf einem Smartphone: Solange der Finger den Bildschirm berührt, gibt es eine Eingabequelle mit dem Profil "generic-touchscreen". Danach verschwindet sie wieder.
Der Vorteil gegenüber requestHitTestSource(): Sie müssen nicht bei jeder neuen Berührung eine neue Hit-Test-Quelle anfordern. Eine einzige Quelle liefert in jedem Frame über XRFrame.getHitTestResultsForTransientInput() Ergebnisse für alle gerade aktiven Eingaben, die zum angegebenen Profil passen. So bekommen Sie ohne asynchrone Verzögerung Treffer mit der realen Umgebung (Boden, Tischflächen), zum Beispiel um ein virtuelles Objekt genau dort zu platzieren, wo der Nutzer hintippt.
Voraussetzung ist eine Sitzung, die mit dem Feature "hit-test" angefordert wurde (in requiredFeatures oder optionalFeatures). Ohne dieses Feature wird das Promise abgelehnt. Geben Sie die Quelle mit XRTransientInputHitTestSource.cancel() wieder frei, sobald Sie sie nicht mehr brauchen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | Object | Konfigurationsobjekt mit den unten aufgeführten Eigenschaften. | |
| $options.profile Pflicht | string | Eingabeprofil, das zu den Einträgen in XRInputSource.profiles passen muss, z. B. "generic-touchscreen" für Berührungen auf Handheld-Geräten. |
|
| $options.entityTypes | Array<"point"|"plane"|"mesh"> | ["plane"] | Arten von realen Objekten, die beim Hit-Test berücksichtigt werden: "point" (Merkmalspunkte), "plane" (erkannte Ebenen) und "mesh" (Geometrienetze). |
| $options.offsetRay | XRRay | new XRRay() | Strahl, der relativ zum Ziel-Strahl (targetRaySpace) der Eingabequelle verschoben wird. Standardmäßig verläuft er vom Ursprung entlang der negativen Z-Achse. |
Rückgabewert
XRTransientInputHitTestSource-Objekt erfüllt wird. Es wird mit einer DOMException abgelehnt: NotSupportedError, wenn das Feature "hit-test" nicht aktiviert ist; InvalidStateError, wenn die Sitzung bereits beendet ist; NotAllowedError, wenn die Anfrage nicht erlaubt ist (z. B. bei zu vielen gleichzeitigen Quellen).Beispiele
AR-Sitzung starten und Hit-Test-Quelle für Touch-Eingaben anfordern
const startAR = async () => {
if (!(await navigator.xr?.isSessionSupported('immersive-ar'))) {
console.log('immersive-ar wird nicht unterstützt');
return;
}
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['hit-test', 'local-floor']
});
const touchHitSource = await session.requestHitTestSourceForTransientInput({
profile: 'generic-touchscreen',
entityTypes: ['plane', 'point']
});
console.log('Hit-Test-Quelle bereit:', touchHitSource);
return { session, touchHitSource };
};
// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#ar-button').addEventListener('click', startAR);
Treffer pro Frame auswerten und Objekt beim Antippen platzieren
const setupPlacement = async (session, placeObject) => {
const refSpace = await session.requestReferenceSpace('local-floor');
const hitSource = await session.requestHitTestSourceForTransientInput({
profile: 'generic-touchscreen'
});
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
// Ein Eintrag je aktiver transienter Eingabe (z. B. je Finger)
const inputResults = frame.getHitTestResultsForTransientInput(hitSource);
for (const { inputSource, results } of inputResults) {
if (results.length === 0) continue;
const pose = results[0].getPose(refSpace);
if (pose) {
const { x, y, z } = pose.transform.position;
placeObject(pose.transform.matrix);
console.log(`Treffer (${inputSource.handedness}): ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
}
}
};
session.requestAnimationFrame(onFrame);
return hitSource;
};
Fehlerbehandlung und Aufräumen beim Sitzungsende
const requestTouchHitTest = async (session) => {
try {
const source = await session.requestHitTestSourceForTransientInput({
profile: 'generic-touchscreen',
offsetRay: new XRRay({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: -1 })
});
session.addEventListener('end', () => {
source.cancel(); // Ressourcen freigeben
console.log('Hit-Test-Quelle freigegeben');
}, { once: true });
return source;
} catch (err) {
if (err.name === 'NotSupportedError') {
console.warn('Feature "hit-test" wurde für die Sitzung nicht aktiviert.');
} else {
console.error('Hit-Test nicht möglich:', err.name, err.message);
}
return null;
}
};
// Wichtig · Fallstricke
- Experimentell: Die Methode gehört zum WebXR Hit Test Module. Sie ist praktisch nur in Chromium-Browsern auf Android (ARCore) und im Meta Quest Browser verfügbar. Firefox und Safari unterstützen sie nicht. Prüfen Sie die Unterstützung vorher mit
navigator.xr.isSessionSupported('immersive-ar'). - Die Methode funktioniert nur in einem sicheren Kontext (HTTPS). Außerdem muss die Sitzung mit dem Feature
"hit-test"angefordert worden sein. Sonst wird das Promise mitNotSupportedErrorabgelehnt. - Das Profil muss exakt passen. Passt keine Eingabequelle zu
profile, liefertgetHitTestResultsForTransientInput()einfach ein leeres Array. Es gibt keinen Fehler, deshalb bleibt ein Tippfehler leicht unbemerkt. - Die Ergebnisse gelten nur für den aktuellen Frame. Speichern Sie keine
XRFrame-Objekte oder Posen über den Callback hinaus. Für dauerhaft verankerte Objekte eignen sich Anker (XRHitTestResult.createAnchor()). - Wie viele Hit-Test-Quellen gleichzeitig erlaubt sind, hängt vom Gerät ab. Rufen Sie
cancel()auf, wenn Sie eine Quelle nicht mehr brauchen. Fordern Sie nicht pro Berührung eine neue Quelle an, denn das ist genau der Fall, für den diese Methode gedacht ist. entityTypes: ["mesh"]wird nicht von allen Geräten unterstützt. Nicht unterstützte Typen werden ignoriert oder führen zu einer Ablehnung.