---
title: orbitControls
description: Creates shared drag-orbit + wheel-zoom controls that drive a camera (or any node) around a target point. Input adjusts goal values; `update(deltaTime)` eases the current state toward them and writes the node's transform, so it composes with `frameLoop()` and on-demand rendering alike.
---

# orbitControls



## Import

```ts
import { orbitControls, type OrbitControlsOptions } from "vgpu/scene";
```

## Signature

```ts
declare function orbitControls(
  node: import("vgpu/scene").SceneNode,
  options?: import("vgpu/scene").OrbitControlsOptions,
): import("vgpu/scene").OrbitControls;
```

## Parameters

| Param               | Type                   | Required | Default       | Notes                                                                               |
| ------------------- | ---------------------- | -------- | ------------- | ----------------------------------------------------------------------------------- |
| node                | `SceneNode`            | ✔        | —             | Usually a camera; any node with `set()`/`lookAt()` works.                           |
| options.element     | `OrbitControlsElement` | ✖        | —             | Pointer/wheel source (usually the canvas). Omit for programmatic-only control.      |
| options.target      | `Vec3Like`             | ✖        | `[0, 0, 0]`   | World-space orbit/look-at point.                                                    |
| options.damping     | `number`               | ✖        | `0.1`         | Easing time constant in seconds (\~63% convergence). `0` applies input immediately. |
| options.rotateSpeed | `number`               | ✖        | `0.005`       | Drag sensitivity in radians per pixel.                                              |
| options.zoomSpeed   | `number`               | ✖        | `1`           | Wheel zoom sensitivity multiplier.                                                  |
| options.distance    | `{ min?, max? }`       | ✖        | —             | Zoom clamp range.                                                                   |
| options.pitch       | `{ min?, max? }`       | ✖        | ±(π/2 − 0.01) | Pitch limits in radians; defaults keep the camera off the poles.                    |

**Returns:** `OrbitControls` with `update()`, `set()`, `dispose()`, and `yaw`/`pitch`/`distance`/`target` state.
**Throws:** `VGPU-SCENE-VALUE-INVALID` for malformed `target` vectors.

## Examples

```ts
import { clock, init, frameLoop } from "vgpu";
import { orbitControls, perspectiveCamera } from "vgpu/scene";

declare const canvas: HTMLCanvasElement;

const gpu = await init();
const camera = perspectiveCamera({ fov: 45, position: [2, 2, 3], target: [0, 0, 0] });
const controls = orbitControls(camera, { element: canvas, damping: 0.1 });

frameLoop(gpu, () => {
  controls.update(clock(gpu).deltaTime); // explicit update, no hidden rAF
});
```

## Notes

* The initial yaw/pitch/distance pose is derived from the node's current position relative to `target`.
* `update()` returns `true` only when the node moved — use it to skip re-rendering static frames.
* Replaces the per-example `installOrbitInput`/`installDragOrbit` copies; one shared implementation.
* **See also:** `OrbitControls`, `OrbitControlsOptions`, `perspectiveCamera`.

***

# OrbitControls

Class returned by `orbitControls()`.

## Import

```ts
import type { OrbitControls } from "vgpu/scene";
```

## Signature

```ts
declare class OrbitControls {
  update(deltaTime?: number): boolean;
  set(values: import("vgpu/scene").OrbitControlsValues): this;
  dispose(): void;
  readonly yaw: number;
  readonly pitch: number;
  readonly distance: number;
  readonly target: Float32Array;
}
```

## Examples

```ts
import { orbitControls, perspectiveCamera } from "vgpu/scene";

const camera = perspectiveCamera({ fov: 45, position: [0, 0, 5], target: [0, 0, 0] });
const controls = orbitControls(camera, { damping: 0 });
controls.set({ yaw: Math.PI / 2, distance: 8 });
controls.update();
controls.dispose();
```

## Notes

* `set()` jumps immediately (state and goal); pointer/wheel input eases through `damping`.
* `dispose()` removes DOM listeners; the node keeps its last transform.
* **See also:** `orbitControls`, `OrbitControlsValues`.

***

# OrbitControlsElement

Structural event-target contract so controls work with an `HTMLCanvasElement` without requiring DOM types, and with mocks in Node tests.

## Import

```ts
import type { OrbitControlsElement } from "vgpu/scene";
```

## Signature

```ts
interface OrbitControlsElement {
  addEventListener(type: string, listener: (event: never) => void, options?: { passive?: boolean } | boolean): void;
  removeEventListener(type: string, listener: (event: never) => void): void;
  setPointerCapture?(pointerId: number): void;
  releasePointerCapture?(pointerId: number): void;
}

// (listener parameters are typed loosely in the real declaration so the DOM's
// overloaded addEventListener stays assignable)
```

## Examples

```ts
import type { OrbitControlsElement } from "vgpu/scene";

declare const canvas: HTMLCanvasElement;
const element: OrbitControlsElement = canvas;
void element;
```

## Notes

* Listened events: `pointerdown`, `pointermove`, `pointerup`, `pointercancel`, `wheel` (non-passive).
* **See also:** `orbitControls`.

***

# OrbitControlsOptions

Options accepted by `orbitControls()`.

## Import

```ts
import type { OrbitControlsOptions } from "vgpu/scene";
```

## Signature

```ts
interface OrbitControlsOptions {
  readonly element?: import("vgpu/scene").OrbitControlsElement;
  readonly target?: import("vgpu/scene").Vec3Like;
  readonly damping?: number;
  readonly rotateSpeed?: number;
  readonly zoomSpeed?: number;
  readonly distance?: { readonly min?: number; readonly max?: number };
  readonly pitch?: { readonly min?: number; readonly max?: number };
  readonly label?: string;
}
```

## Examples

```ts
import { orbitControls, perspectiveCamera } from "vgpu/scene";

orbitControls(perspectiveCamera({ fov: 45, position: [0, 0, 5] }), {
  target: [0, 0.5, 0],
  distance: { min: 1, max: 20 },
  pitch: { min: -1.2, max: 1.2 },
});
```

## Notes

* **See also:** `orbitControls`, `OrbitControlsElement`.

***

# OrbitControlsValues

Values accepted by `OrbitControls.set()`; applied immediately to both state and goal.

## Import

```ts
import type { OrbitControlsValues } from "vgpu/scene";
```

## Signature

```ts
interface OrbitControlsValues {
  readonly yaw?: number;
  readonly pitch?: number;
  readonly distance?: number;
  readonly target?: import("vgpu/scene").Vec3Like;
}
```

## Examples

```ts
import { orbitControls, perspectiveCamera } from "vgpu/scene";

const controls = orbitControls(perspectiveCamera({ fov: 45, position: [0, 0, 5] }));
controls.set({ pitch: 0.4, distance: 6 });
```

## Notes

* `pitch` and `distance` are clamped to the configured limits.
* **See also:** `OrbitControls`.


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)