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

gizmos.mddocs/

0

# Gizmos

1

2

Interactive tools and visual helpers for development and user interaction. These components provide intuitive interfaces for object manipulation, scene navigation, and visual debugging.

3

4

## Capabilities

5

6

### PivotControls

7

8

Interactive pivot controls for object transformation with visual feedback and constraint options.

9

10

```typescript { .api }

11

/**

12

* Interactive pivot controls for object transformation

13

* @param props - Pivot controls configuration

14

* @returns JSX element for pivot controls

15

*/

16

function PivotControls(props: PivotControlsProps): JSX.Element;

17

18

interface PivotControlsProps {

19

/** Enable/disable controls, true */

20

enabled?: boolean;

21

/** Gizmo scale, 1 */

22

scale?: number;

23

/** Line width for control handles, 2.5 */

24

lineWidth?: number;

25

/** Fixed screen size (pixels), false */

26

fixed?: boolean;

27

/** Position offset from object */

28

offset?: [number, number, number];

29

/** Starting rotation */

30

rotation?: [number, number, number];

31

/** Transform matrix */

32

matrix?: Matrix4;

33

/** Anchor point for transformations */

34

anchor?: [number, number, number];

35

/** Display mode flags */

36

displayValues?: boolean;

37

/** Disable X axis, false */

38

disableAxisX?: boolean;

39

/** Disable Y axis, false */

40

disableAxisY?: boolean;

41

/** Disable Z axis, false */

42

disableAxisZ?: boolean;

43

/** Disable rotation, false */

44

disableRotations?: boolean;

45

/** Disable scaling, false */

46

disableScaling?: boolean;

47

/** Disable sliders, false */

48

disableSliders?: boolean;

49

/** Active axes color */

50

activeAxes?: [boolean, boolean, boolean];

51

/** Translation limits */

52

translationLimits?: [[number, number], [number, number], [number, number]];

53

/** Rotation limits */

54

rotationLimits?: [[number, number], [number, number], [number, number]];

55

/** Scale limits */

56

scaleLimits?: [[number, number], [number, number], [number, number]];

57

/** Drag start callback */

58

onDragStart?: () => void;

59

/** Drag callback */

60

onDrag?: (local: Matrix4, deltaL: Matrix4, world: Matrix4, deltaW: Matrix4) => void;

61

/** Drag end callback */

62

onDragEnd?: () => void;

63

}

64

```

65

66

**Usage Examples:**

67

68

```typescript

69

import { PivotControls } from '@react-three/drei';

70

71

// Basic pivot controls

72

<PivotControls>

73

<mesh>

74

<boxGeometry />

75

<meshStandardMaterial />

76

</mesh>

77

</PivotControls>

78

79

// Advanced pivot controls with constraints

80

<PivotControls

81

scale={100}

82

lineWidth={3}

83

fixed

84

anchor={[0, 0, 0]}

85

disableRotations

86

translationLimits={[[-5, 5], [0, 10], [-5, 5]]}

87

onDragStart={() => console.log('Drag started')}

88

onDrag={(local, deltaL, world, deltaW) => {

89

// Handle transformation

90

console.log('Local matrix:', local);

91

console.log('World matrix:', world);

92

}}

93

onDragEnd={() => console.log('Drag ended')}

94

>

95

<mesh>

96

<sphereGeometry />

97

<meshStandardMaterial color="orange" />

98

</mesh>

99

</PivotControls>

100

101

// Multiple constrained pivot controls

102

function ConstrainedObject() {

103

const [position, setPosition] = useState([0, 0, 0]);

104

105

return (

106

<PivotControls

107

anchor={[0, 0, 0]}

108

disableAxisY

109

onDrag={(local) => {

110

const pos = new Vector3().setFromMatrixPosition(local);

111

setPosition([pos.x, 0, pos.z]); // Constrain to ground plane

112

}}

113

>

114

<mesh position={position}>

115

<cylinderGeometry />

116

<meshStandardMaterial />

117

</mesh>

118

</PivotControls>

119

);

120

}

121

```

122

123

### DragControls

124

125

Drag controls for intuitive object manipulation with 3D mouse interaction.

126

127

```typescript { .api }

128

/**

129

* Drag controls for object manipulation

130

* @param props - Drag controls configuration

131

* @returns JSX element for drag controls

132

*/

133

function DragControls(props: DragControlsProps): JSX.Element;

134

135

interface DragControlsProps {

136

/** Child objects to make draggable */

137

children: React.ReactNode;

138

/** Axis constraints: 'x' | 'y' | 'z' | 'xy' | 'xz' | 'yz' */

139

axisLock?: 'x' | 'y' | 'z' | 'xy' | 'xz' | 'yz';

140

/** Auto transform objects, true */

141

autoTransform?: boolean;

142

/** Transform matrix */

143

matrix?: Matrix4;

144

/** Drag start callback */

145

onDragStart?: (event: { object: Object3D; pointerId: number; point: Vector3 }) => void;

146

/** Drag callback */

147

onDrag?: (event: { object: Object3D; pointerId: number; point: Vector3; delta: Vector3 }) => void;

148

/** Drag end callback */

149

onDragEnd?: (event: { object: Object3D; pointerId: number }) => void;

150

/** Hover start callback */

151

onHoverStart?: (event: { object: Object3D }) => void;

152

/** Hover end callback */

153

onHoverEnd?: (event: { object: Object3D }) => void;

154

}

155

```

156

157

**Usage Examples:**

158

159

```typescript

160

import { DragControls } from '@react-three/drei';

161

162

// Basic drag controls

163

<DragControls>

164

<mesh>

165

<boxGeometry />

166

<meshStandardMaterial />

167

</mesh>

168

<mesh position={[2, 0, 0]}>

169

<sphereGeometry />

170

<meshStandardMaterial />

171

</mesh>

172

</DragControls>

173

174

// Constrained dragging

175

<DragControls

176

axisLock="y"

177

onDragStart={(e) => console.log('Dragging:', e.object.name)}

178

onDrag={(e) => {

179

// Custom drag behavior

180

e.object.rotation.y += e.delta.x * 0.01;

181

}}

182

>

183

<mesh name="draggable-box">

184

<boxGeometry />

185

<meshStandardMaterial color="red" />

186

</mesh>

187

</DragControls>

188

189

// Advanced drag system

190

function DraggableSystem() {

191

const [draggedObject, setDraggedObject] = useState(null);

192

193

return (

194

<DragControls

195

onDragStart={(e) => {

196

setDraggedObject(e.object);

197

e.object.material.emissive.setHex(0x444444);

198

}}

199

onDragEnd={(e) => {

200

setDraggedObject(null);

201

e.object.material.emissive.setHex(0x000000);

202

}}

203

onHoverStart={(e) => {

204

document.body.style.cursor = 'grab';

205

}}

206

onHoverEnd={(e) => {

207

document.body.style.cursor = 'auto';

208

}}

209

>

210

{objects.map((obj, i) => (

211

<DraggableObject key={i} {...obj} />

212

))}

213

</DragControls>

214

);

215

}

216

```

217

218

### Grid

219

220

3D grid helper for spatial reference and scene organization.

221

222

```typescript { .api }

223

/**

224

* 3D grid helper for spatial reference

225

* @param props - Grid configuration

226

* @returns JSX element for grid display

227

*/

228

function Grid(props: GridProps): JSX.Element;

229

230

interface GridProps extends Omit<ThreeElements['gridHelper'], 'ref'> {

231

/** Grid cell size, 1 */

232

cellSize?: number;

233

/** Grid section size, 10 */

234

sectionSize?: number;

235

/** Grid color, #999999 */

236

cellColor?: ReactThreeFiber.Color;

237

/** Section color, #555555 */

238

sectionColor?: ReactThreeFiber.Color;

239

/** Grid size, 100 */

240

args?: [number, number];

241

/** Infinite grid, false */

242

infiniteGrid?: boolean;

243

/** Fade distance, 100 */

244

fadeDistance?: number;

245

/** Fade strength, 1 */

246

fadeStrength?: number;

247

/** Follow camera, false */

248

followCamera?: boolean;

249

/** Side to render, DoubleSide */

250

side?: Side;

251

}

252

253

type GridMaterialType = {

254

cellSize: number;

255

sectionSize: number;

256

cellColor: Color;

257

sectionColor: Color;

258

fadeDistance: number;

259

fadeStrength: number;

260

};

261

```

262

263

**Usage Examples:**

264

265

```typescript

266

import { Grid } from '@react-three/drei';

267

268

// Basic grid

269

<Grid args={[100, 100]} />

270

271

// Customized grid

272

<Grid

273

cellSize={0.5}

274

sectionSize={5}

275

cellColor={'#ff0000'}

276

sectionColor={'#0000ff'}

277

args={[50, 50]}

278

position={[0, -1, 0]}

279

/>

280

281

// Infinite grid that follows camera

282

<Grid

283

infiniteGrid

284

fadeDistance={50}

285

fadeStrength={2}

286

followCamera

287

cellSize={1}

288

sectionSize={10}

289

/>

290

```

291

292

### GizmoHelper

293

294

Container for 3D gizmos with positioning and interaction management.

295

296

```typescript { .api }

297

/**

298

* Container for 3D gizmos with positioning

299

* @param props - Gizmo helper configuration

300

* @returns JSX element for gizmo container

301

*/

302

function GizmoHelper(props: GizmoHelperProps): JSX.Element;

303

304

interface GizmoHelperProps {

305

/** Gizmo alignment, 'bottom-right' */

306

alignment?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';

307

/** Gizmo margin, [80, 80] */

308

margin?: [number, number];

309

/** Render on top, false */

310

onTop?: boolean;

311

/** Auto update, false */

312

onUpdate?: () => void;

313

/** Render priority, 1 */

314

renderPriority?: number;

315

/** Child gizmos */

316

children: React.ReactNode;

317

}

318

```

319

320

**Usage Examples:**

321

322

```typescript

323

import { GizmoHelper, GizmoViewport } from '@react-three/drei';

324

325

// Basic gizmo helper

326

<GizmoHelper alignment="bottom-right" margin={[80, 80]}>

327

<GizmoViewport

328

axisColors={['red', 'green', 'blue']}

329

labelColor="black"

330

/>

331

</GizmoHelper>

332

```

333

334

### GizmoViewport

335

336

3D viewport gizmo for camera orientation display and interaction.

337

338

```typescript { .api }

339

/**

340

* 3D viewport gizmo for camera orientation

341

* @param props - Gizmo viewport configuration

342

* @returns JSX element for viewport gizmo

343

*/

344

function GizmoViewport(props: GizmoViewportProps): JSX.Element;

345

346

interface GizmoViewportProps {

347

/** Axis colors [x, y, z], ['red', 'green', 'blue'] */

348

axisColors?: [string, string, string];

349

/** Axis head scale, 1 */

350

axisHeadScale?: number;

351

/** Label color, 'black' */

352

labelColor?: string;

353

/** Axis scale, [0.8, 0.05, 0.8] */

354

axisScale?: [number, number, number];

355

/** Labels ['X', 'Y', 'Z'] */

356

labels?: [string, string, string];

357

/** Font size, 16 */

358

fontSize?: number;

359

/** Font family, 'Inter' */

360

font?: string;

361

}

362

```

363

364

### GizmoViewcube

365

366

3D viewcube gizmo for camera navigation and preset views.

367

368

```typescript { .api }

369

/**

370

* 3D viewcube gizmo for camera navigation

371

* @param props - Gizmo viewcube configuration

372

* @returns JSX element for viewcube gizmo

373

*/

374

function GizmoViewcube(props: GizmoViewcubeProps): JSX.Element;

375

376

interface GizmoViewcubeProps {

377

/** Face text color, 'white' */

378

textColor?: string;

379

/** Face background color, '#f0f0f0' */

380

color?: string;

381

/** Hover color, '#999' */

382

hoverColor?: string;

383

/** Edge color, 'black' */

384

strokeColor?: string;

385

/** Font size, 0.5 */

386

fontSize?: number;

387

/** Font family, 'Inter' */

388

font?: string;

389

/** Face labels */

390

faces?: string[];

391

/** Corner radius, 0.1 */

392

cornerRadius?: number;

393

/** Opacity, 1 */

394

opacity?: number;

395

}

396

```

397

398

**Usage Examples:**

399

400

```typescript

401

import { GizmoHelper, GizmoViewcube, GizmoViewport } from '@react-three/drei';

402

403

// Complete gizmo system

404

<GizmoHelper alignment="bottom-right" margin={[100, 100]}>

405

<GizmoViewcube

406

faces={['Right', 'Left', 'Top', 'Bottom', 'Front', 'Back']}

407

color="#f8f8f8"

408

hoverColor="#ddd"

409

strokeColor="#666"

410

textColor="#333"

411

fontSize={0.6}

412

/>

413

</GizmoHelper>

414

415

// Combined viewport and viewcube

416

<GizmoHelper alignment="top-left" margin={[80, 80]}>

417

<group>

418

<GizmoViewcube />

419

<GizmoViewport

420

axisColors={['#ff3653', '#8adb00', '#2c8fff']}

421

labelColor="white"

422

/>

423

</group>

424

</GizmoHelper>

425

```

426

427

### TransformControls

428

429

Advanced transformation gizmo with multiple modes and precise control.

430

431

```typescript { .api }

432

/**

433

* Advanced transformation gizmo (from core controls)

434

* @param props - Transform controls configuration

435

* @returns JSX element for transformation gizmo

436

*/

437

function TransformControls(props: TransformControlsProps): JSX.Element;

438

439

interface TransformControlsProps extends Omit<ThreeElement<TransformControlsImpl>, 'ref' | 'args'> {

440

/** Object to transform */

441

object?: Object3D;

442

/** Camera to use */

443

camera?: Camera;

444

/** DOM element for events */

445

domElement?: HTMLElement;

446

/** Control mode: 'translate' | 'rotate' | 'scale' */

447

mode?: 'translate' | 'rotate' | 'scale';

448

/** Transform space: 'world' | 'local' */

449

space?: 'world' | 'local';

450

/** Gizmo size, 1 */

451

size?: number;

452

/** Show X axis, true */

453

showX?: boolean;

454

/** Show Y axis, true */

455

showY?: boolean;

456

/** Show Z axis, true */

457

showZ?: boolean;

458

/** Translation snap */

459

translationSnap?: number;

460

/** Rotation snap */

461

rotationSnap?: number;

462

/** Scale snap */

463

scaleSnap?: number;

464

/** Dragging change callback */

465

onDragging?: (dragging: boolean) => void;

466

/** Object change callback */

467

onChange?: () => void;

468

}

469

```

470

471

## Integration Patterns

472

473

### Multi-Gizmo Scene

474

475

```typescript

476

function EditorScene() {

477

const [selectedObject, setSelectedObject] = useState(null);

478

const [transformMode, setTransformMode] = useState('translate');

479

const [showGrid, setShowGrid] = useState(true);

480

481

return (

482

<>

483

{/* Scene grid */}

484

{showGrid && (

485

<Grid

486

cellSize={1}

487

sectionSize={10}

488

args={[100, 100]}

489

position={[0, -0.01, 0]}

490

/>

491

)}

492

493

{/* Draggable objects */}

494

<DragControls

495

onDragStart={(e) => setSelectedObject(e.object)}

496

onDragEnd={() => setSelectedObject(null)}

497

>

498

<SceneObjects />

499

</DragControls>

500

501

{/* Transform controls for selected object */}

502

{selectedObject && (

503

<TransformControls

504

object={selectedObject}

505

mode={transformMode}

506

onDragging={(dragging) => {

507

// Disable orbit controls while transforming

508

orbitControlsRef.current.enabled = !dragging;

509

}}

510

/>

511

)}

512

513

{/* Camera gizmos */}

514

<GizmoHelper alignment="bottom-right" margin={[80, 80]}>

515

<GizmoViewcube />

516

<GizmoViewport />

517

</GizmoHelper>

518

519

{/* UI Controls */}

520

<Html fullscreen>

521

<div className="editor-ui">

522

<button onClick={() => setTransformMode('translate')}>

523

Translate

524

</button>

525

<button onClick={() => setTransformMode('rotate')}>

526

Rotate

527

</button>

528

<button onClick={() => setTransformMode('scale')}>

529

Scale

530

</button>

531

<button onClick={() => setShowGrid(!showGrid)}>

532

Toggle Grid

533

</button>

534

</div>

535

</Html>

536

</>

537

);

538

}

539

```

540

541

### Constrained Manipulation

542

543

```typescript

544

function ConstrainedEditor() {

545

return (

546

<>

547

{/* Ground-constrained dragging */}

548

<DragControls axisLock="xz">

549

<GroundObjects />

550

</DragControls>

551

552

{/* Y-axis only movement */}

553

<PivotControls

554

disableAxisX

555

disableAxisZ

556

disableRotations

557

disableScaling

558

translationLimits={[null, [0, 10], null]}

559

>

560

<ElevatorPlatform />

561

</PivotControls>

562

563

{/* Rotation-only controls */}

564

<PivotControls

565

anchor={[0, 0, 0]}

566

disableSliders

567

disableScaling

568

rotationLimits={[null, [-Math.PI, Math.PI], null]}

569

>

570

<RotatingDoor />

571

</PivotControls>

572

</>

573

);

574

}

575

```

576

577

### Gizmo State Management

578

579

```typescript

580

function GizmoSystem() {

581

const [gizmoVisible, setGizmoVisible] = useState(true);

582

const [gizmoMode, setGizmoMode] = useState('translate');

583

const [activeObject, setActiveObject] = useState(null);

584

585

// Keyboard shortcuts

586

useEffect(() => {

587

const handleKeyDown = (e) => {

588

switch (e.key) {

589

case 'g':

590

setGizmoMode('translate');

591

break;

592

case 'r':

593

setGizmoMode('rotate');

594

break;

595

case 's':

596

setGizmoMode('scale');

597

break;

598

case 'h':

599

setGizmoVisible(!gizmoVisible);

600

break;

601

}

602

};

603

604

window.addEventListener('keydown', handleKeyDown);

605

return () => window.removeEventListener('keydown', handleKeyDown);

606

}, [gizmoVisible]);

607

608

return (

609

<>

610

{gizmoVisible && (

611

<>

612

<Grid infiniteGrid fadeDistance={100} />

613

614

<PivotControls

615

enabled={activeObject !== null}

616

scale={gizmoMode === 'scale' ? 150 : 100}

617

onDragStart={() => console.log(`${gizmoMode} started`)}

618

onDragEnd={() => console.log(`${gizmoMode} ended`)}

619

>

620

{activeObject && <primitive object={activeObject} />}

621

</PivotControls>

622

623

<GizmoHelper alignment="bottom-right">

624

<GizmoViewcube />

625

</GizmoHelper>

626

</>

627

)}

628

</>

629

);

630

}

631

```

632

633

### Performance-Optimized Gizmos

634

635

```typescript

636

function OptimizedGizmos() {

637

// Only render gizmos when needed

638

const [showGizmos, setShowGizmos] = useState(false);

639

const [selectedObjects, setSelectedObjects] = useState([]);

640

641

// Throttle gizmo updates

642

const throttledUpdate = useCallback(

643

throttle((matrix) => {

644

// Update object transform

645

updateObjectTransform(matrix);

646

}, 16), // 60 FPS

647

[]

648

);

649

650

return (

651

<>

652

{/* Conditional gizmo rendering */}

653

{showGizmos && selectedObjects.length > 0 && (

654

<PivotControls

655

onDrag={throttledUpdate}

656

lineWidth={window.devicePixelRatio > 1 ? 1 : 2}

657

>

658

{selectedObjects.map(obj => (

659

<primitive key={obj.uuid} object={obj} />

660

))}

661

</PivotControls>

662

)}

663

664

{/* Low-impact grid */}

665

<Grid

666

infiniteGrid

667

fadeDistance={50}

668

cellSize={1}

669

args={[20, 20]} // Smaller grid for performance

670

/>

671

</>

672

);

673

}

674

```

675

676

### RoundedBox

677

678

Shape utility for creating rounded box geometries.

679

680

```typescript { .api }

681

/**

682

* Creates rounded box geometry with configurable corner radius

683

* @param props - RoundedBox configuration props

684

* @returns JSX element for rounded box mesh

685

*/

686

function RoundedBox(props: RoundedBoxProps): JSX.Element;

687

688

interface RoundedBoxProps extends Omit<ThreeElements['mesh'], 'ref' | 'args'> {

689

/** Box dimensions [width, height, depth] */

690

args?: [number?, number?, number?];

691

/** Corner radius, 0.05 */

692

radius?: number;

693

/** Surface smoothness, 4 */

694

smoothness?: number;

695

/** Bevel segments for corners, 3 */

696

bevelSegments?: number;

697

/** Extrude steps, 1 */

698

steps?: number;

699

/** Crease angle for sharp edges, 0.4 */

700

creaseAngle?: number;

701

}

702

```

703

704

### ScreenQuad

705

706

Utility component for creating screen-aligned quad geometries.

707

708

```typescript { .api }

709

/**

710

* Creates screen-aligned quad geometry for post-processing effects

711

* @param props - ScreenQuad configuration props

712

* @returns JSX element for screen quad mesh

713

*/

714

function ScreenQuad(props: ScreenQuadProps): JSX.Element;

715

716

interface ScreenQuadProps extends Omit<ThreeElements['mesh'], 'ref'> {

717

/** Material for the quad */

718

material?: Material;

719

}

720

```