OrbitControls
OrbitControls adds pointer-driven orbiting, wheel and pinch zoom, optional panning, automatic rotation, and configurable camera bounds to an HTML canvas. The controls maintain a camera position around a target without depending on a specific renderer, scene graph, or GPU backend.
Usage
import {OrbitControls} from '@luma.gl/engine';
import {Matrix4} from '@math.gl/core';
const canvas = document.querySelector<HTMLCanvasElement>('#canvas')!;
const controls = new OrbitControls(canvas, {
target: [0, 1, 0],
distance: 8,
minDistance: 2,
maxDistance: 24,
pitch: 0.35,
autoRotate: true,
autoRotateSpeed: 0.2
});
const viewMatrix = new Matrix4();
function render(timeMilliseconds: number): void {
controls.update(timeMilliseconds);
viewMatrix.lookAt({
eye: controls.getEyePosition(),
center: controls.props.target,
up: [0, 1, 0]
});
// Use viewMatrix to draw the current animation frame.
requestAnimationFrame(render);
}
requestAnimationFrame(render);
Call controls.destroy() when the canvas or its owning application is removed.
Types
OrbitPosition
type OrbitPosition = [number, number, number];
A three-component world-space position. OrbitControls copies configured targets, so mutating the original target array does not move the orbit center.
OrbitControlsProps
type OrbitControlsProps = {
target?: Readonly<OrbitPosition>;
distance?: number;
yaw?: number;
pitch?: number;
minDistance?: number;
maxDistance?: number;
minPitch?: number;
maxPitch?: number;
rotateSpeed?: number;
pitchSpeed?: number;
zoomSpeed?: number;
enabled?: boolean;
enableZoom?: boolean;
enablePan?: boolean;
panSpeed?: number;
autoRotate?: boolean;
autoRotateSpeed?: number;
onInteractionStart?: () => void;
};
| Property | Default | Description |
|---|---|---|
target | [0, 0, 0] | World-space point around which the camera rotates. |
distance | 10 | Initial distance from the orbit target, in world-space units. |
yaw | 0 | Initial horizontal orbit angle in radians. |
pitch | 0.25 | Initial vertical orbit angle in radians. |
minDistance | 1 | Minimum distance from the target. |
maxDistance | 100 | Maximum distance from the target. |
minPitch | -Math.PI / 2 + 0.01 | Lowest allowed pitch angle in radians. |
maxPitch | Math.PI / 2 - 0.01 | Highest allowed pitch angle in radians. |
rotateSpeed | 0.006 | Horizontal rotation applied per CSS pixel of pointer movement, in radians. |
pitchSpeed | rotateSpeed | Optional vertical rotation applied per CSS pixel. Negative values invert the vertical drag direction. |
zoomSpeed | 0.001 | Exponential wheel-zoom sensitivity. |
enabled | true | Whether pointer, touch, wheel, and automatic camera interactions are active. |
enableZoom | true | Whether mouse-wheel and two-finger pinch gestures can change the camera distance. |
enablePan | false | Whether Shift-dragging and two-finger touch movement can pan the orbit target. |
panSpeed | 0.0018 | Target movement per CSS pixel, scaled by the current camera distance. |
autoRotate | false | Whether update() automatically advances the horizontal angle. |
autoRotateSpeed | 0.1 | Automatic horizontal rotation speed in radians per second. |
onInteractionStart | undefined | Optional callback invoked when a pointer, touch, or wheel interaction begins. Adding a second finger does not start a separate interaction. |
Properties
canvas: HTMLCanvasElement
The canvas receiving pointer and wheel events.
props
The resolved orbit configuration. Defaults are filled in when controls are created. Read props.target when constructing a camera view matrix; call setProps() to update configuration and apply new camera values consistently.
yaw: number
Current horizontal orbit angle in radians. Applications can read or adjust this value directly between frames.
pitch: number
Current vertical orbit angle in radians. Pointer interaction and setProps() clamp this value between minPitch and maxPitch.
distance: number
Current world-space distance from the target. Wheel gestures, pinch gestures, and setProps() clamp this value between minDistance and maxDistance.
Methods
constructor(canvas: HTMLCanvasElement, props?: OrbitControlsProps)
Creates controls for canvas, attaches pointer and wheel listeners, clamps the initial pitch and distance, and sets the canvas cursor and touch-action style for orbit gestures.
canvas must be a real HTML canvas or an equivalent object implementing DOM pointer-event methods. An OffscreenCanvas does not provide the necessary interaction APIs.
update(timeMilliseconds: number): void
Advances automatic rotation using an absolute animation-frame timestamp in milliseconds. Call once per frame before reading getEyePosition().
- The first call records the initial timestamp without changing the angle.
- Automatic rotation is paused while one or more pointers are interacting with the canvas.
- Rotation resumes from the manually adjusted angle after the pointer is released.
- Elapsed time is clamped to 100 milliseconds to avoid large camera jumps after an inactive tab or stalled frame.
- Backward timestamps do not reverse the orbit.
function onAnimationFrame(timeMilliseconds: number): void {
controls.update(timeMilliseconds);
const cameraPosition = controls.getEyePosition();
drawFrame(cameraPosition);
}
getEyePosition(): OrbitPosition
Returns the current world-space camera position computed from target, yaw, pitch, and distance.
At yaw: 0 and pitch: 0, the camera is positioned on the positive Z side of its target. Positive pitch moves the camera upward.
setProps(props: OrbitControlsProps): void
Updates the orbit configuration without replacing the controls or reattaching event listeners.
Specified camera values are applied immediately. If pitch or distance limits change, existing values are clamped to the new limits. An updated target is copied rather than retained by reference.
controls.setProps({
target: sceneBounds.center,
distance: sceneBounds.radius * 2,
minDistance: sceneBounds.radius * 0.25,
maxDistance: sceneBounds.radius * 8
});
Changing yaw, pitch, or distance through setProps() also updates the configured camera pose used by reset().
setAutoRotate(autoRotate: boolean): void
Enables or disables automatic rotation without resetting the current angle.
controls.setAutoRotate(false);
reset(): void
Restores the configured yaw, pitch, and distance. The restored pitch and distance respect the current configured bounds.
destroy(): void
Removes all pointer and wheel listeners, releases active pointer capture, and restores the canvas cursor and touch-action styles that existed before construction.
Interaction behavior
- Drag with the primary mouse button, one touch pointer, or a pen pointer to orbit the target.
- Scroll the wheel to zoom. Wheel deltas are bounded before applying exponential zoom so large trackpad or mouse events cannot produce an excessive distance jump.
- Pinch two touch points apart to zoom in or together to zoom out. Pinch distance respects the same configured bounds as wheel zoom.
- Set
enablePan: trueto pan with Shift-dragging or by moving the midpoint of a two-finger touch gesture. - Pointer capture keeps every active touch or pointer associated with the canvas, even outside its bounds.
- Releasing one finger resumes one-pointer orbiting without a positional jump;
pointercancel, disabling controls, anddestroy()release the relevant captures. - The controls compute camera coordinates only; rendering, camera projection, matrix updates, and redraw scheduling remain the application's responsibility.
@luma.gl/experimentalcontinues to re-exportOrbitControlsfor compatibility, but new applications should import the class and its types from@luma.gl/engine.