Signatur
Beschreibung
Die Methode entries() von XRInputSourceArray liefert einen Array-Iterator, der für jede Eingabequelle ein Paar [index, inputSource] ausgibt. Der Index ist eine Zahl ab 0, der Wert ein XRInputSource-Objekt, also z. B. ein Controller, eine getrackte Hand oder ein Blick- bzw. Bildschirm-Eingabestrahl.
XRInputSourceArray ist ein array-ähnliches Objekt, das über XRSession.inputSources abrufbar ist. Es verhält sich ähnlich wie ein Array (length, Index-Zugriff, forEach(), keys(), values(), entries(), Iteration mit for...of), ist aber kein echtes Array: Methoden wie map() oder filter() gibt es darauf nicht.
entries() ist dann nützlich, wenn du beim Durchlaufen neben der Eingabequelle auch ihre Position im Array brauchst, etwa für Debug-Ausgaben, für die Zuordnung zu vorher angelegten 3D-Modellen oder um die Liste per Array.from() in ein echtes Array umzuwandeln.
Beachte, dass sich die Liste zur Laufzeit ändert, sobald Controller verbunden oder getrennt werden. Der Index ist deshalb kein dauerhafter Bezeichner für ein bestimmtes Gerät. Für eine stabile Zuordnung nutzt du das XRInputSource-Objekt selbst oder dessen handedness.
Rückgabewert
[index, XRInputSource] liefert.Beispiele
Alle Eingabequellen mit Index protokollieren
// Innerhalb einer laufenden immersiven WebXR-Sitzung
const logInputSources = (session) => {
for (const [index, source] of session.inputSources.entries()) {
console.log(`#${index}: ${source.handedness} / ${source.targetRayMode}`, source.profiles);
}
};
const session = await navigator.xr.requestSession('immersive-vr');
session.addEventListener('inputsourceschange', () => logInputSources(session));
Controller-Posen im Frame-Loop abfragen
const onXRFrame = (time, frame) => {
const session = frame.session;
session.requestAnimationFrame(onXRFrame);
for (const [i, source] of session.inputSources.entries()) {
if (!source.gripSpace) continue; // z. B. bei 'gaze' oder 'screen'
const pose = frame.getPose(source.gripSpace, refSpace);
if (pose) {
const { x, y, z } = pose.transform.position;
controllerModels[i]?.position.set(x, y, z);
}
}
};
const session = await navigator.xr.requestSession('immersive-vr');
const refSpace = await session.requestReferenceSpace('local');
const controllerModels = []; // z. B. three.js-Objekte
session.requestAnimationFrame(onXRFrame);
In ein echtes Array bzw. eine Map umwandeln
const session = await navigator.xr.requestSession('immersive-ar');
// Echte Array-Methoden stehen danach zur Verfügung
const pairs = Array.from(session.inputSources.entries());
const trackedHands = pairs.filter(([, src]) => src.hand !== null);
// Nach Händigkeit indizieren – stabiler als der numerische Index
const byHand = new Map(pairs.map(([, src]) => [src.handedness, src]));
console.log(trackedHands.length, byHand.has('right'));
// Wichtig · Fallstricke
- Kompatibilität: Die WebXR Device API gibt es vor allem in Chromium-basierten Browsern (Chrome, Edge, Samsung Internet) und im Meta Quest Browser. Safari unterstützt WebXR nur eingeschränkt (visionOS), Firefox auf dem Desktop gar nicht. Prüfe vorab mit
'xr' in navigatorundnavigator.xr.isSessionSupported(). - Sicherer Kontext: WebXR funktioniert nur über HTTPS bzw.
localhost. Eine immersive Sitzung muss durch eine Nutzeraktion (z. B. einen Klick) gestartet werden. - Veränderliche Liste: Die Liste ändert sich, wenn Geräte verbunden oder getrennt werden. Das meldet das Ereignis
inputsourceschange. Verlass dich nicht auf einen festen Index pro Controller. - Kein echtes Array:
map(),filter()usw. fehlen. Wandle die Liste bei Bedarf mitArray.from()oder dem Spread-Operator um. - Der Iterator bildet eine Momentaufnahme des Live-Objekts. Speichere ihn nicht über mehrere Frames hinweg, sondern rufe
entries()in jedem Frame neu auf. - Nicht jede Eingabequelle hat einen
gripSpace, etwa beitargetRayMode'gaze'oder'screen'. Prüfe das vor dem Aufruf vongetPose().