Signatur
Beschreibung
Die Eigenschaft inputSource eines XRInputSourceEvent verweist auf die XRInputSource, von der das Ereignis ausgeht. Solche Ereignisse löst eine XRSession bei primären Aktionen aus: select, selectstart, selectend (z. B. Abzug oder Pinch-Geste) sowie squeeze, squeezestart und squeezeend (Greiftaste).
Über das zurückgegebene Objekt lässt sich feststellen, welches Gerät die Aktion ausgelöst hat: handedness ("left", "right", "none"), targetRayMode ("tracked-pointer", "gaze", "screen", "transient-pointer"), profiles, gamepad und hand. Vor allem aber liefern targetRaySpace und gripSpace die Räume, mit denen du über event.frame.getPose() die Position und Ausrichtung des Zeigestrahls genau zum Zeitpunkt des Ereignisses bestimmen kannst.
Typische Anwendungen sind Raycasting zum Auswählen von Objekten, das Unterscheiden von linker und rechter Hand (z. B. linke Hand = Menü, rechte Hand = Werkzeug) und die Zuordnung von selectstart/selectend-Paaren zum selben Controller bei Drag-Interaktionen.
Rückgabewert
XRInputSource-Objekt des Eingabegeräts, das das Ereignis erzeugt hat. Während die Quelle verbunden ist, bleibt es dieselbe Objektinstanz, daher kann man es als Schlüssel (z. B. in einer Map) verwenden.Beispiele
Hand des auslösenden Controllers bestimmen
const startXR = async () => {
const session = await navigator.xr.requestSession('immersive-vr');
session.addEventListener('select', (event) => {
const { handedness, targetRayMode, profiles } = event.inputSource;
console.log(`Auswahl durch ${handedness}-Eingabe (${targetRayMode})`);
console.log('Profile:', profiles.join(', '));
});
};
// Muss durch eine Nutzergeste ausgelöst werden
document.querySelector('#vr-button').addEventListener('click', startXR);
Zeigestrahl zum Zeitpunkt des Ereignisses auslesen (Raycasting)
let refSpace;
const onSelect = (event) => {
// event.frame ist nur während des Handlers gültig
const pose = event.frame.getPose(event.inputSource.targetRaySpace, refSpace);
if (!pose) return; // Tracking verloren
const { position, orientation } = pose.transform;
console.log('Strahlursprung:', position.x.toFixed(2), position.y.toFixed(2), position.z.toFixed(2));
console.log('Ausrichtung (Quaternion):', orientation.w.toFixed(2));
// hier: Strahl gegen die Szene testen und Treffer hervorheben
};
const init = async () => {
const session = await navigator.xr.requestSession('immersive-vr');
refSpace = await session.requestReferenceSpace('local');
session.addEventListener('select', onSelect);
};
document.querySelector('#vr-button').addEventListener('click', init);
Drag-Interaktion pro Controller verfolgen
const activeDrags = new Map();
const setupDragging = (session) => {
session.onselectstart = (event) => {
activeDrags.set(event.inputSource, { start: performance.now() });
console.log(`Drag gestartet: ${event.inputSource.handedness}`);
};
session.onselectend = (event) => {
const drag = activeDrags.get(event.inputSource);
if (!drag) return;
const dauer = Math.round(performance.now() - drag.start);
console.log(`Drag beendet: ${event.inputSource.handedness} nach ${dauer} ms`);
activeDrags.delete(event.inputSource);
};
// Getrennte Controller aufräumen
session.addEventListener('inputsourceschange', ({ removed }) => {
removed.forEach((source) => activeDrags.delete(source));
});
};
document.querySelector('#vr-button').addEventListener('click', async () => {
const session = await navigator.xr.requestSession('immersive-vr');
setupDragging(session);
});
// Wichtig · Fallstricke
- Schreibgeschützt: Die Eigenschaft wird im Konstruktor
new XRInputSourceEvent(type, { frame, inputSource })gesetzt und kann danach nicht geändert werden. - Frame nur kurz gültig:
event.frame.getPose()funktioniert nur synchron im Handler. Wer die Pose später braucht (z. B. nach einemawaitoder in einemsetTimeout), muss sie im Handler kopieren. Sonst gibt es einenInvalidStateError. - Transiente Quellen: Bei
targetRayMode"screen"(AR auf dem Smartphone) oder"transient-pointer"gibt es die Quelle nur für die Dauer der Geste. Sie steht daher oft nicht dauerhaft insession.inputSources. getPose()kannnullzurückgeben, wenn das Tracking verloren geht. Prüfe das immer.inputSource.gamepadundinputSource.handkönnennullsein, je nach Gerät und aktivierten Features (hand-trackingmuss beirequestSessionangefordert werden).- Kompatibilität: WebXR braucht einen sicheren Kontext (HTTPS). Unterstützt wird es vor allem in Chromium-Browsern und im Meta Quest Browser. Firefox und Safari auf dem Desktop unterstützen es nicht. Safari auf der Apple Vision Pro unterstützt WebXR, dort wird der Pinch als
"transient-pointer"gemeldet. Prüfe die Unterstützung vorher mitnavigator.xr?.isSessionSupported().