threlte logo
@threlte/extras

<OrbitControls>

<OrbitControls> allow the camera to orbit around a target while ensuring a fixed camera up vector. If the camera orbits over the “north” or “south” poles, the camera experiences a “gimbal lock” that forces the scene to rotate until it is rightside up. This type of camera control is commonly used for showing off 3D models of products because it prevents them from ever appearing upside down. For an alternative camera controller, see <TrackballControls>.

The <OrbitControls> component must be a direct child of a camera component and will mount itself to that camera.

<script lang="ts">
  import { Canvas } from '@threlte/core'

  import Scene from './Scene.svelte'
  import Settings from './Settings.svelte'

  let autoRotate = $state(false)
  let enableDamping = $state(true)
  let rotateSpeed = $state(1)
  let zoomToCursor = $state(false)
  let zoomSpeed = $state(1)
  let minPolarAngle = $state(0)
  let maxPolarAngle = $state(Math.PI)
  let enableZoom = $state(true)
</script>

<div>
  <Canvas>
    <Scene
      {enableDamping}
      {autoRotate}
      {rotateSpeed}
      {zoomToCursor}
      {zoomSpeed}
      {minPolarAngle}
      {maxPolarAngle}
      {enableZoom}
    />
  </Canvas>
</div>

<Settings
  bind:enableDamping
  bind:autoRotate
  bind:rotateSpeed
  bind:zoomToCursor
  bind:zoomSpeed
  bind:minPolarAngle
  bind:maxPolarAngle
  bind:enableZoom
/>

<style>
  div {
    position: relative;
    height: 100%;
    width: 100%;
    background-color: rgb(14, 22, 37);
  }
</style>
<script lang="ts">
  import { T } from '@threlte/core'
  import { Gizmo, OrbitControls } from '@threlte/extras'

  import { BoxGeometry, MeshStandardMaterial } from 'three'

  interface Props {
    autoRotate: boolean
    enableDamping: boolean
    rotateSpeed: number
    zoomToCursor: boolean
    zoomSpeed: number
    minPolarAngle: number
    maxPolarAngle: number
    enableZoom: boolean
  }

  let {
    autoRotate,
    enableDamping,
    rotateSpeed,
    zoomToCursor,
    zoomSpeed,
    minPolarAngle,
    maxPolarAngle,
    enableZoom
  }: Props = $props()
</script>

<T.PerspectiveCamera
  makeDefault
  position={[10, 5, 10]}
  lookAt.y={0.5}
>
  <OrbitControls
    {enableDamping}
    {autoRotate}
    {rotateSpeed}
    {zoomToCursor}
    {zoomSpeed}
    {minPolarAngle}
    {maxPolarAngle}
    {enableZoom}
  >
    <Gizmo />
  </OrbitControls>
</T.PerspectiveCamera>

<T.DirectionalLight
  position.y={10}
  position.z={10}
/>
<T.AmbientLight intensity={0.3} />

<T.GridHelper args={[10, 10]} />

<T.Mesh position.y={1}>
  <T.BoxGeometry args={[2, 2, 2]} />
  <T.MeshStandardMaterial />
</T.Mesh>
<script lang="ts">
  import { Checkbox, Pane, ThemeUtils, Slider } from 'svelte-tweakpane-ui'

  interface Props {
    autoRotate: boolean
    enableDamping: boolean
    rotateSpeed: number
    zoomToCursor: boolean
    zoomSpeed: number
    minPolarAngle: number
    maxPolarAngle: number
    enableZoom: boolean
  }

  let {
    autoRotate = $bindable(),
    enableDamping = $bindable(),
    rotateSpeed = $bindable(),
    zoomToCursor = $bindable(),
    zoomSpeed = $bindable(),
    minPolarAngle = $bindable(),
    maxPolarAngle = $bindable(),
    enableZoom = $bindable()
  }: Props = $props()
</script>

<Pane
  theme={ThemeUtils.presets.light}
  position="fixed"
  title="OrbitControls"
>
  <Checkbox
    bind:value={autoRotate}
    label="autoRotate"
  />
  <Checkbox
    bind:value={enableDamping}
    label="enableDamping"
  />
  <Checkbox
    bind:value={enableZoom}
    label="enableZoom"
  />
  <Checkbox
    bind:value={zoomToCursor}
    label="zoomToCursor"
  />
  <Slider
    label="rotateSpeed"
    bind:value={rotateSpeed}
    min={0.1}
    max={2}
    step={0.1}
  />
  <Slider
    label="zoomSpeed"
    bind:value={zoomSpeed}
    min={0.1}
    max={2}
    step={0.1}
  />
  <Slider
    label="minPolarAngle"
    bind:value={minPolarAngle}
    min={0}
    max={Math.PI}
    step={0.1}
  />
  <Slider
    label="maxPolarAngle"
    bind:value={maxPolarAngle}
    min={0}
    max={Math.PI}
    step={0.1}
  />
</Pane>

This example shows off just a few of the configurable properties of <OrbitControls>. To see all 30+ properties, consult the Three.js docs.

Usage

<script>
  import { OrbitControls } from '@threlte/extras'
  import { T } from '@threlte/core'
</script>

<T.PerspectiveCamera
  makeDefault
  fov={50}
>
  <OrbitControls enableDamping />
</T.PerspectiveCamera>

<OrbitControls> is a light wrapper that will use its parent as the target camera and the DOM element the renderer is rendering to as the DOM element to listen to pointer events.

Component Signature

<OrbitControls> extends <T . OrbitControls> and supports all its props, slot props, bindings and events.