Three.js OrbitControls: Setup, Options & Alternatives

OrbitControls lets a user orbit, zoom and pan a Three.js camera around a target point using mouse or touch. Instantiate it with the camera and the renderer's DOM element, call controls.update() in your render loop, and set enableDamping = true for smooth, inertia-based movement rather than instant stops.

Last updated . Verified against three.js r181.

Read the FAQJump to code

Basic setup

OrbitControls lives in the examples/addons, not the core package, so it's imported separately. The essentials: pass it your camera and the renderer's canvas element, and call controls.update() every frame if damping or auto-rotate is enabled. Without that call, damping won't animate and auto-rotate won't spin.

The target property is the point the camera orbits around. Set it to your subject's position (default is the world origin) before the first render, or the initial framing will look off.

The options that actually matter

  • enableDamping + dampingFactor. Without damping, orbiting stops the instant you release the mouse, which feels mechanical. With it (try dampingFactor: 0.05), movement eases out for almost no cost. Requires calling controls.update() every frame.
  • minDistance / maxDistance. Prevents zooming inside an object or zooming out to nothing. Almost always worth setting explicitly rather than trusting the defaults.
  • minPolarAngle / maxPolarAngle. Restricts vertical orbit, useful to stop a user flipping the camera upside-down or diving under the ground plane.
  • autoRotate + autoRotateSpeed. A slow automatic spin when idle, common on product-viewer and portfolio scenes. Pauses automatically on user interaction, but note it also requires controls.update() every frame to animate.
  • enablePan. Often disabled (false) for product/object viewers where the subject should always stay centered.

When OrbitControls isn't the right control scheme

OrbitControls assumes an orbit-around-a-point interaction, which fits product viewers, model inspectors and portfolio pieces. For other interaction models, Three.js ships alternatives in the same addons folder: FirstPersonControls and PointerLockControls for FPS-style walk-throughs, FlyControls for free 6-DOF flight, TrackballControls for unconstrained rotation (no fixed "up" axis, useful for inspecting an object from any angle including upside-down), and ArcballControls for a gizmo-driven variant of orbit controls with visible rotation handles.

Code

OrbitControls setup (r181)
1import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
2
3const controls = new OrbitControls(camera, renderer.domElement)
4controls.target.set(0, 1, 0)
5controls.enableDamping = true
6controls.dampingFactor = 0.05
7controls.minDistance = 2
8controls.maxDistance = 20
9controls.maxPolarAngle = Math.PI / 2 // don't let the camera go under the ground
10
11renderer.setAnimationLoop(() => {
12 controls.update() // required for damping/autoRotate
13 renderer.render(scene, camera)
14})
Same setup: controls are renderer-agnostic
1// OrbitControls only touches the camera, not the material system, so it
2// works identically with WebGPURenderer. No TSL-specific changes needed.
3import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
4
5const controls = new OrbitControls(camera, renderer.domElement)
6controls.enableDamping = true
7
8renderer.setAnimationLoop(() => {
9 controls.update()
10 renderer.render(scene, camera)
11})

Learn this properly

Learn Practical TSL

Your First Node Material

Set up your first scene and camera before adding interactive controls.

Start the lesson (6 minutes)

Frequently asked questions

Why don't my OrbitControls have any damping effect?

Two things are required together: set controls.enableDamping = true, and call controls.update() inside your render loop every frame. Damping animates over time, so skipping the update() call means nothing moves after the initial input.

How do I stop OrbitControls from zooming inside an object?

Set controls.minDistance to a value slightly larger than your object's radius, and controls.maxDistance to cap how far out a user can zoom.

What's the difference between OrbitControls and TrackballControls?

OrbitControls keeps a fixed "up" direction and clamps vertical rotation by default, which suits most scenes. TrackballControls has no fixed up-axis, so the camera can rotate freely including upside-down, useful for inspecting an object from literally any angle.

Keep reading