or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

abstractions.mdcameras.mdcontrols.mdgizmos.mdhooks.mdindex.mdloaders.mdmaterials.mdperformance.mdstaging.mdweb-integration.md

web-integration.mddocs/

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

```