0
# Web Integration
1
2
Web-specific components for HTML overlays, browser integration, and user interface elements. These components bridge the gap between 3D scenes and traditional HTML/DOM elements.
3
4
## Capabilities
5
6
### Html
7
8
HTML overlay integration with 3D positioning, occlusion, and transform options.
9
10
```typescript { .api }
11
/**
12
* HTML overlay integration with 3D positioning
13
* @param props - HTML overlay configuration
14
* @returns JSX element for HTML content in 3D space
15
*/
16
function Html(props: HtmlProps): JSX.Element;
17
18
interface HtmlProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'ref'> {
19
/** Prepend content to existing, false */
20
prepend?: boolean;
21
/** Center content horizontally and vertically, false */
22
center?: boolean;
23
/** Use CSS 3D transforms, false */
24
transform?: boolean;
25
/** Render as CSS 2D sprite, false */
26
sprite?: boolean;
27
/** Portal HTML into custom container */
28
portal?: HTMLElement;
29
/** Distance factor for sprites, 10 */
30
distanceFactor?: number;
31
/** Occlusion objects or settings */
32
occlude?: React.RefObject<Object3D>[] | boolean | 'raycast' | 'blending';
33
/** Occlusion blending amount, 0 */
34
occlusionOpacity?: number;
35
/** Z-index for HTML, 0 */
36
zIndexRange?: [number, number];
37
/** Calculate position function */
38
calculatePosition?: CalculatePosition;
39
/** As container div, false */
40
as?: string;
41
/** Wrapper class */
42
wrapperClass?: string;
43
/** Pointer events, 'auto' */
44
pointerEvents?: 'auto' | 'none';
45
/** Full screen, false */
46
fullscreen?: boolean;
47
/** Epsilon for depth testing, 0 */
48
eps?: number;
49
}
50
51
type CalculatePosition = (
52
obj: Object3D,
53
camera: Camera,
54
size: { width: number; height: number }
55
) => [number, number];
56
```
57
58
**Usage Examples:**
59
60
```typescript
61
import { Html } from '@react-three/drei';
62
63
// Basic HTML overlay
64
<mesh position={[0, 0, 0]}>
65
<sphereGeometry />
66
<meshStandardMaterial />
67
<Html position={[0, 1, 0]} center>
68
<div style={{ background: 'white', padding: '10px', borderRadius: '5px' }}>
69
<h1>3D Label</h1>
70
<p>This HTML content follows the 3D object</p>
71
</div>
72
</Html>
73
</mesh>
74
75
// HTML with occlusion
76
<Html
77
position={[0, 0, 0]}
78
occlude={[meshRef, meshRef2]}
79
center
80
transform
81
>
82
<div className="tooltip">
83
This content is occluded by 3D objects
84
</div>
85
</Html>
86
87
// Sprite-style HTML
88
<Html
89
position={[5, 2, 0]}
90
sprite
91
distanceFactor={15}
92
center
93
>
94
<div className="ui-element">
95
<button onClick={() => console.log('Clicked!')}>
96
3D Button
97
</button>
98
</div>
99
</Html>
100
```
101
102
### ScrollControls
103
104
Scroll-based camera controls with virtual scrolling and smooth interpolation.
105
106
```typescript { .api }
107
/**
108
* Scroll-based camera controls with virtual scrolling
109
* @param props - Scroll controls configuration
110
* @returns JSX element for scroll controls
111
*/
112
function ScrollControls(props: ScrollControlsProps): JSX.Element;
113
114
/**
115
* Scroll component for accessing scroll state
116
* @param props - Scroll component props
117
* @returns JSX element with scroll context
118
*/
119
function Scroll(props: ScrollProps): JSX.Element;
120
121
interface ScrollControlsProps extends Omit<ThreeElements['group'], 'ref'> {
122
/** Virtual scroll area height, 1 */
123
pages?: number;
124
/** Scroll distance factor, 1 */
125
distance?: number;
126
/** Smooth scrolling damping, 4 */
127
damping?: number;
128
/** Horizontal scrolling, false */
129
horizontal?: boolean;
130
/** Infinite scrolling, false */
131
infinite?: boolean;
132
/** Enable zoom, true */
133
enabled?: boolean;
134
/** Style overrides for scroll area */
135
style?: React.CSSProperties;
136
/** Inner scroll area style */
137
innerStyle?: React.CSSProperties;
138
}
139
140
interface ScrollProps {
141
/** HTML scroll content, false */
142
html?: boolean;
143
}
144
145
interface ScrollControlsState {
146
/** Current scroll offset [0-1] */
147
offset: number;
148
/** Current scroll delta */
149
delta: number;
150
/** Scroll progress [0-1] */
151
progress: number;
152
/** Scroll range [start, end] */
153
range(from: number, to: number): number;
154
/** Curve interpolation */
155
curve(from: number, to: number, margin?: number): number;
156
/** Visible range check */
157
visible(from: number, to: number, margin?: number): boolean;
158
}
159
```
160
161
**Usage Examples:**
162
163
```typescript
164
import { ScrollControls, Scroll, useScroll } from '@react-three/drei';
165
166
// Basic scroll controls
167
<ScrollControls pages={3} damping={4}>
168
<Scroll>
169
{/* 3D content that responds to scroll */}
170
<AnimatedMesh />
171
</Scroll>
172
<Scroll html>
173
{/* HTML content overlay */}
174
<div style={{ position: 'absolute', top: '100vh' }}>
175
<h1>Page 2</h1>
176
</div>
177
<div style={{ position: 'absolute', top: '200vh' }}>
178
<h1>Page 3</h1>
179
</div>
180
</Scroll>
181
</ScrollControls>
182
183
// Animated content based on scroll
184
function AnimatedMesh() {
185
const scroll = useScroll();
186
const meshRef = useRef();
187
188
useFrame(() => {
189
if (meshRef.current) {
190
meshRef.current.rotation.y = scroll.offset * Math.PI * 2;
191
meshRef.current.position.y = scroll.curve(0, 1, 0.1) * 5;
192
}
193
});
194
195
return (
196
<mesh ref={meshRef}>
197
<boxGeometry />
198
<meshStandardMaterial />
199
</mesh>
200
);
201
}
202
```
203
204
### Loader
205
206
Loading UI component with progress indicators and customizable styling.
207
208
```typescript { .api }
209
/**
210
* Loading UI component with progress indicators
211
* @param props - Loader configuration
212
* @returns JSX element for loading UI
213
*/
214
function Loader(props: LoaderProps): JSX.Element;
215
216
interface LoaderProps {
217
/** Container class name */
218
containerClassName?: string;
219
/** Inner class name */
220
innerClassName?: string;
221
/** Bar class name */
222
barClassName?: string;
223
/** Data class name */
224
dataClassName?: string;
225
/** Data interpolation function */
226
dataInterpolation?: (p: number) => string;
227
/** Initial text, 'Loading...' */
228
initialText?: string;
229
}
230
```
231
232
**Usage Examples:**
233
234
```typescript
235
import { Loader } from '@react-three/drei';
236
import { Suspense } from 'react';
237
238
// Basic loader
239
function App() {
240
return (
241
<>
242
<Canvas>
243
<Suspense fallback={null}>
244
<Scene />
245
</Suspense>
246
</Canvas>
247
<Loader />
248
</>
249
);
250
}
251
252
// Custom loader
253
<Loader
254
containerClassName="my-loader"
255
barClassName="my-progress-bar"
256
dataInterpolation={(p) => `Loading ${(p * 100).toFixed(0)}%`}
257
initialText="Preparing 3D Scene..."
258
/>
259
```
260
261
### useCursor
262
263
Hook for changing cursor styles based on hover state.
264
265
```typescript { .api }
266
/**
267
* Hook for changing cursor styles based on hover state
268
* @param hovered - Whether element is hovered
269
* @param cursor - Cursor style to apply, 'pointer'
270
*/
271
function useCursor(hovered: boolean, cursor?: string): void;
272
```
273
274
**Usage Examples:**
275
276
```typescript
277
import { useCursor } from '@react-three/drei';
278
279
function InteractiveMesh() {
280
const [hovered, setHovered] = useState(false);
281
useCursor(hovered, 'pointer');
282
283
return (
284
<mesh
285
onPointerEnter={() => setHovered(true)}
286
onPointerLeave={() => setHovered(false)}
287
onClick={() => console.log('Clicked!')}
288
>
289
<boxGeometry />
290
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
291
</mesh>
292
);
293
}
294
295
// Custom cursor styles
296
function CustomInteractive() {
297
const [hovered, setHovered] = useState(false);
298
useCursor(hovered, 'grab');
299
300
return (
301
<mesh
302
onPointerEnter={() => setHovered(true)}
303
onPointerLeave={() => setHovered(false)}
304
>
305
<sphereGeometry />
306
<meshStandardMaterial />
307
</mesh>
308
);
309
}
310
```
311
312
### KeyboardControls
313
314
Keyboard input mapping and state management for 3D interactions.
315
316
```typescript { .api }
317
/**
318
* Keyboard input mapping and state management
319
* @param props - Keyboard controls configuration
320
* @returns JSX element for keyboard controls context
321
*/
322
function KeyboardControls<T = string>(props: KeyboardControlsProps<T>): JSX.Element;
323
324
/**
325
* Hook for accessing keyboard control state
326
* @returns Keyboard controls API
327
*/
328
function useKeyboardControls(): KeyboardControlsApi;
329
330
interface KeyboardControlsProps<T = string> {
331
/** Key mapping configuration */
332
map: KeyboardControlsEntry<T>[];
333
/** Child components */
334
children: React.ReactNode;
335
/** DOM element to attach listeners, document */
336
domElement?: HTMLElement;
337
}
338
339
interface KeyboardControlsEntry<T = string> {
340
/** Control name */
341
name: T;
342
/** Key codes */
343
keys: string[];
344
}
345
346
interface KeyboardControlsApi {
347
/** Get current key state */
348
forward: boolean;
349
backward: boolean;
350
left: boolean;
351
right: boolean;
352
jump: boolean;
353
[key: string]: boolean;
354
}
355
```
356
357
**Usage Examples:**
358
359
```typescript
360
import { KeyboardControls, useKeyboardControls } from '@react-three/drei';
361
362
// Keyboard controls setup
363
const map = [
364
{ name: 'forward', keys: ['ArrowUp', 'KeyW'] },
365
{ name: 'backward', keys: ['ArrowDown', 'KeyS'] },
366
{ name: 'left', keys: ['ArrowLeft', 'KeyA'] },
367
{ name: 'right', keys: ['ArrowRight', 'KeyD'] },
368
{ name: 'jump', keys: ['Space'] },
369
];
370
371
function App() {
372
return (
373
<KeyboardControls map={map}>
374
<Canvas>
375
<Player />
376
</Canvas>
377
</KeyboardControls>
378
);
379
}
380
381
// Using keyboard input
382
function Player() {
383
const { forward, backward, left, right, jump } = useKeyboardControls();
384
const playerRef = useRef();
385
386
useFrame((state, delta) => {
387
if (playerRef.current) {
388
const speed = 5;
389
if (forward) playerRef.current.position.z -= speed * delta;
390
if (backward) playerRef.current.position.z += speed * delta;
391
if (left) playerRef.current.position.x -= speed * delta;
392
if (right) playerRef.current.position.x += speed * delta;
393
if (jump) playerRef.current.position.y += speed * delta;
394
}
395
});
396
397
return (
398
<mesh ref={playerRef}>
399
<boxGeometry />
400
<meshStandardMaterial />
401
</mesh>
402
);
403
}
404
```
405
406
### PresentationControls
407
408
Presentation-style controls optimized for showcasing 3D models and products.
409
410
```typescript { .api }
411
/**
412
* Presentation-style controls for showcasing 3D content
413
* @param props - Presentation controls configuration
414
* @returns JSX element for presentation controls
415
*/
416
function PresentationControls(props: PresentationControlProps): JSX.Element;
417
418
interface PresentationControlProps extends Omit<ThreeElements['group'], 'ref'> {
419
/** Enable controls, true */
420
enabled?: boolean;
421
/** Global rotation constraint, true */
422
global?: boolean;
423
/** Cursor grab, true */
424
cursor?: boolean;
425
/** Snap to positions */
426
snap?: boolean | { mass: number; tension: number };
427
/** Rotation speed, 1 */
428
speed?: number;
429
/** Zoom settings */
430
zoom?: { min: number; max: number };
431
/** Polar angle limits [min, max] */
432
polar?: [number, number];
433
/** Azimuth angle limits [min, max] */
434
azimuth?: [number, number];
435
/** Config for spring animation */
436
config?: { mass: number; tension: number; friction: number };
437
}
438
```
439
440
**Usage Examples:**
441
442
```typescript
443
import { PresentationControls } from '@react-three/drei';
444
445
// Basic presentation controls
446
<PresentationControls enabled global>
447
<mesh>
448
<torusGeometry />
449
<meshNormalMaterial />
450
</mesh>
451
</PresentationControls>
452
453
// Constrained presentation
454
<PresentationControls
455
enabled
456
global
457
cursor
458
snap={{ mass: 4, tension: 1500 }}
459
rotation={[0, 0, 0]}
460
polar={[-Math.PI / 3, Math.PI / 3]}
461
azimuth={[-Math.PI / 1.4, Math.PI / 2]}
462
>
463
<Model />
464
</PresentationControls>
465
```
466
467
### Select
468
469
Object selection system with multi-select support and event handling.
470
471
```typescript { .api }
472
/**
473
* Object selection system with multi-select support
474
* @param props - Select configuration
475
* @returns JSX element for selection context
476
*/
477
function Select(props: SelectProps): JSX.Element;
478
479
interface SelectProps {
480
/** Multiple selection, false */
481
multiple?: boolean;
482
/** Selection box styling */
483
box?: boolean;
484
/** Child components */
485
children: React.ReactNode;
486
/** Selection change handler */
487
onChange?: (selected: Object3D[]) => void;
488
/** Filter function for selectable objects */
489
filter?: (objects: Object3D[]) => Object3D[];
490
}
491
```
492
493
## Integration Patterns
494
495
### HTML and 3D Interaction
496
497
```typescript
498
function Interactive3DHTML() {
499
const [selected, setSelected] = useState(null);
500
501
return (
502
<>
503
<mesh onClick={() => setSelected('sphere')}>
504
<sphereGeometry />
505
<meshStandardMaterial color={selected === 'sphere' ? 'red' : 'blue'} />
506
<Html position={[0, 1.5, 0]} center occlude>
507
<div className="label">
508
<h3>Interactive Sphere</h3>
509
<button onClick={() => setSelected(null)}>Reset</button>
510
</div>
511
</Html>
512
</mesh>
513
</>
514
);
515
}
516
```
517
518
### Scroll-Driven Animation
519
520
```typescript
521
function ScrollDrivenScene() {
522
return (
523
<ScrollControls pages={4} damping={0.1}>
524
<Scroll>
525
<ScrollAnimatedContent />
526
</Scroll>
527
<Scroll html>
528
<div className="scroll-content">
529
{/* HTML content synchronized with 3D */}
530
</div>
531
</Scroll>
532
</ScrollControls>
533
);
534
}
535
536
function ScrollAnimatedContent() {
537
const data = useScroll();
538
const meshRef = useRef();
539
540
useFrame(() => {
541
if (meshRef.current && data) {
542
// Animate based on scroll position
543
meshRef.current.rotation.y = data.offset * Math.PI * 2;
544
meshRef.current.scale.setScalar(1 + data.range(0, 1/4) * 2);
545
}
546
});
547
548
return (
549
<mesh ref={meshRef}>
550
<boxGeometry />
551
<meshNormalMaterial />
552
</mesh>
553
);
554
}
555
```
556
557
### Loading States
558
559
```typescript
560
function App() {
561
return (
562
<>
563
<Canvas>
564
<Suspense fallback={<LoadingFallback />}>
565
<Scene />
566
</Suspense>
567
</Canvas>
568
<Loader />
569
</>
570
);
571
}
572
573
function LoadingFallback() {
574
return (
575
<Html center>
576
<div className="loading-3d">
577
<div className="spinner"></div>
578
<p>Loading 3D assets...</p>
579
</div>
580
</Html>
581
);
582
}
583
```
584
585
### CycleRaycast
586
587
Component for keyboard-based cycling through raycasted objects.
588
589
```typescript { .api }
590
/**
591
* Provides keyboard-based cycling through raycasted objects
592
* @param props - CycleRaycast configuration props
593
* @returns JSX element for raycasting controls
594
*/
595
function CycleRaycast(props: CycleRaycastProps): JSX.Element;
596
597
interface CycleRaycastProps {
598
/** Callback when selection changes */
599
onChanged?: (hits: THREE.Intersection[], cycle: number) => null;
600
/** Prevent default key behavior, true */
601
preventDefault?: boolean;
602
/** Enable scroll cycling, true */
603
scroll?: boolean;
604
/** Key code for cycling, 9 (Tab) */
605
keyCode?: number;
606
/** Portal element reference */
607
portal?: React.RefObject<HTMLElement>;
608
}
609
```
610
611
### View
612
613
Component for creating multiple viewports within a single canvas.
614
615
```typescript { .api }
616
/**
617
* Creates multiple viewports within a single canvas
618
* @param props - View configuration props
619
* @returns JSX element for viewport rendering
620
*/
621
function View(props: ViewProps): JSX.Element;
622
623
interface ViewProps {
624
/** Viewport index */
625
index?: number;
626
/** Child components */
627
children?: React.ReactNode;
628
/** Viewport tracking element */
629
track?: React.RefObject<HTMLElement>;
630
}
631
```
632
633
### PresentationControls
634
635
Touch and mouse controls for object presentation and interaction.
636
637
```typescript { .api }
638
/**
639
* Touch and mouse controls for object presentation
640
* @param props - PresentationControls configuration props
641
* @returns JSX element for presentation controls
642
*/
643
function PresentationControls(props: PresentationControlProps): JSX.Element;
644
645
interface PresentationControlProps {
646
/** Snap behavior, false */
647
snap?: boolean | number;
648
/** Global controls, false */
649
global?: boolean;
650
/** Show cursor, true */
651
cursor?: boolean;
652
/** Control speed, 1 */
653
speed?: number;
654
/** Zoom factor, 1 */
655
zoom?: number;
656
/** Rotation limits */
657
rotation?: [number, number, number];
658
/** Polar angle limits */
659
polar?: [number, number];
660
/** Azimuth angle limits */
661
azimuth?: [number, number];
662
/** Damping factor, 0.05 */
663
damping?: number;
664
/** Enable controls, true */
665
enabled?: boolean;
666
/** Child components */
667
children?: React.ReactNode;
668
/** DOM element for events */
669
domElement?: HTMLElement;
670
}
671
```