Back openDesk Edu for a sovereign, open-source education — every vote counts.
Vote nowSave products you love by clicking the heart icon.
Praktische Patterns für die Integration von LLMs, VLMs und neuronalen Netzen in immersive XR-Umgebungen — von räumlichen KI-Assistenten bis hin zum Echtzeit-Szenenverständnis.
Spatial UI geht über flache Bildschirme hinaus in 3D-Umgebungen, in denen Benutzer mit Inhalten über ihre Hände, den Blick und Controller interagieren. Das Design für dieses Medium erfordert ein grundlegendes Überdenken von Layout, Typografie, Feedback und Barrierefreiheit.
Dieser Leitfaden behandelt bewährte Muster für den Aufbau räumlicher Interfaces in WebXR, ergänzt durch praktische Code-Beispiele und Designprinzipien aus Produktionsanwendungen.
| Screen UI | Spatial UI |
|---|---|
| Fixer Viewport | Benutzer bewegt sich um Inhalte |
| Maus-/Touch-Input | Hände, Blick, Controller, Sprache |
| CSS-Pixel | Meter der realen Welt |
| 2D-Layout | 3D-Platzierung mit Tiefe |
| Keine physische Ermüdung | Komfort und Ergonomie zählen |
Die Grundregel: Spatial UI sollte sich in der realen Welt natürlich anfühlen, nicht wie ein flacher Bildschirm, der in VR schwebt.
Verwenden Sie Einheiten der realen Welt für das räumliche Layout:
// 1 meter ≈ 1 unit in WebXR
const UI_DISTANCE = 1.5; // arm's reach
const BUTTON_SIZE = 0.08; // 8cm button
const TEXT_HEIGHT = 0.03; // 3cm text for readability
Ein Button, der in Armlänge kleiner als 5 cm ist, lässt sich schwer antippen. Text unter 2 cm wird unleserlich. Testen Sie Ihre Layouts in realen Entfernungen.
Strukturieren Sie Inhalte in Zonen basierend auf der Aufmerksamkeit des Benutzers:
// Spatial zones helper
const ZONES = {
focal: { x: 0, y: 0, z: -1.5 },
peripheral: { x: 1.2, y: 0.3, z: -1.5 },
background: { x: 0, y: 0, z: -5 },
};
Verwenden Sie ein curved billboard für Textpanels, sodass jedes Wort den gleichen Abstand zum Benutzer hat:
const textPanel = new THREE.Mesh(
new THREE.CylinderGeometry(0.8, 0.8, 0.5, 32, 1, true),
textMaterial,
);
textPanel.rotation.x = -Math.PI / 2;
Für Dashboards und datenintensive UIs empfiehlt sich ein scrollbares Panel, zu dem der Benutzer herausgreift, um zu interagieren, ähnlich wie bei einem physischen Tablet.
Benutzer sollten Objekte greifen, tippen und ziehen können, wie sie es in der realen Welt tun würden:
// Three.js drag interaction
controller.addEventListener("select", () => {
const hit = raycast(intersectables);
if (hit) {
hit.object.userData.onSelect?.();
}
});
controller.addEventListener("squeeze", () => {
const grabbed = raycast(grabbables);
if (grabbed) {
attachToController(grabbed.object, controller);
}
});
Nutzen Sie bei Hand-Tracking den Blick (Gaze) zum Anvisieren und das Zusammenkneifen der Finger (Pinch) zur Bestätigung:
if (hand.pinchStrength > 0.8) {
const target = gazeRaycast(scene.children);
if (target) target.userData.onPinch?.();
}
Dieses Muster ist ermüdungsfrei und funktioniert gut auf Geräten ohne Controller (Quest Hand-Tracking, Vision Pro).
| Modus | Anwendungsfall | Implementierung |
|---|---|---|
| World-locked | Menüs, HUDs, Labels | XRSpace mit Anker |
| Body-locked | Toolbars, Inventar | Folgt Kamera-XZ-Position |
| Device-locked | Benachrichtigungen, Warnungen | Overlay-Canvas (selten) |
Räumliche Interaktionen benötigen ein starkes visuelles Feedback, da Benutzer keine physischen Tasten spüren können:
function InteractionFeedback({ hovered, selected, disabled }: FeedbackProps) {
const scale = hovered ? 1.05 : 1;
const color = selected ? "#4ade80" : disabled ? "#6b7280" : "#3b82f6";
const opacity = disabled ? 0.4 : 1;
return (
<mesh scale={scale}>
<planeGeometry args={[0.2, 0.08]} />
<meshStandardMaterial color={color} transparent opacity={opacity} />
</mesh>
);
}
Bieten Sie immer mindestens drei Feedback-Zustände an: idle → hover → active.
Jede Interaktion sollte eine akustische Antwort haben:
function playInteractionSound(type: "hover" | "select" | "error") {
const buffers = {
hover: audioBufferHover,
select: audioBufferClick,
error: audioBufferError,
};
const source = audioContext.createBufferSource();
source.buffer = buffers[type];
source.connect(audioContext.destination);
source.start();
}
Nicht alle Benutzer können in VR klar sehen. Unterstützen Sie:
// Reduce motion for sensitive users
const userPrefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const ANIMATION_DURATION = userPrefersReducedMotion ? 0 : 300;
Spatial UI muss innerhalb des Frame-Budgets bleiben:
| Metrik | Budget |
|---|---|
| Draw Calls (nur UI) | ≤ 20 |
| UI-Triangles | ≤ 10.000 |
| UI-Texturspeicher | ≤ 32 MB |
| Update-Zeit | ≤ 2 ms |
Verwenden Sie instanced meshes für wiederkehrende Elemente (Buttons, Labels):
const buttonInstances = new THREE.InstancedMesh(buttonGeometry, material, MAX_BUTTONS);
Eine minimale Spatial-UI-Komponente:
export function SpatialButton({ position, label, onSelect, disabled }: SpatialButtonProps) {
return (
<group position={position}>
<mesh onClick={onSelect} onPointerOver={() => playInteractionSound("hover")}>
<planeGeometry args={[0.2, 0.08]} />
<meshStandardMaterial
color={disabled ? "#6b7280" : "#3b82f6"}
transparent
opacity={disabled ? 0.4 : 1}
/>
</mesh>
<SpatialText text={label} position={[0, 0, 0.001]} fontSize={0.025} />
</group>
);
}
Das Design von Spatial UI ist noch eine aufstrebende Disziplin. Testen Sie früh, testen Sie oft und priorisieren Sie den Benutzerkomfort vor dem visuellen Feinschliff.