threlte logo
@threlte/extras

<TransformControls>

This component can be used to transform objects in 3D space by adapting a similar interaction model of DCC tools like Blender. Unlike other controls, it is not intended to transform the scenes camera.

The component <TransformControls> needs to be the parent of the component to be transformed.

To accommodate <OrbitControls> or <TrackballControls> as well as a <TransformControls> component in the same scene, the <TransformControls> component is able automatically pause the currently active <OrbitControls> or <TrackballControls> component when the user is interacting with the <TransformControls> component. You can opt out of this behaviour by setting the property autoPauseOrbitControls or autoPauseTrackballControls to false.

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

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

  let controls: '<TrackballControls>' | '<OrbitControls>' = '<OrbitControls>'
</script>

<div>
  <Canvas>
    <Scene />
  </Canvas>
</div>

<Settings bind:controls />

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

  import { BoxGeometry, MeshStandardMaterial, PerspectiveCamera } from 'three'

  export let controls: '<TrackballControls>' | '<OrbitControls>' = '<OrbitControls>'

  let camera: PerspectiveCamera

  $: if (camera && controls === '<OrbitControls>') {
    // This snaps the camera back into a position that makes sense for OrbitControls
    camera.up.set(0, 1, 0)
  }
</script>

<T.PerspectiveCamera
  makeDefault
  position={[10, 5, 10]}
  lookAt.y={0.5}
  bind:ref={camera}
>
  {#if controls === '<TrackballControls>'}
    <TrackballControls />
  {:else if controls === '<OrbitControls>'}
    <OrbitControls />
  {/if}
</T.PerspectiveCamera>

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

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

<TransformControls
  translationSnap={1}
  position.y={1}
>
  <T.Mesh
    geometry={new BoxGeometry(2, 2, 2)}
    material={new MeshStandardMaterial()}
  />
</TransformControls>
<script lang="ts">
  import { Pane, List, ThemeUtils } from 'svelte-tweakpane-ui'

  export let controls: '<TrackballControls>' | '<OrbitControls>' = '<OrbitControls>'
</script>

<Pane
  theme={ThemeUtils.presets.light}
  position="fixed"
  title="TransformControls"
>
  <List
    label="Camera Controls"
    bind:value={controls}
    options={{
      '<TrackballControls>': '<TrackballControls>',
      '<OrbitControls>': '<OrbitControls>'
    }}
  />
</Pane>

Examples

Scene.svelte
<script>
  import { T } from '@threlte/core'
  import { TransformControls } from '@threlte/extras'
  import { MeshStandardMaterial, BoxBufferGeometry } from 'three'
</script>

<TransformControls>
  <T.Mesh
    geometry={new BoxBufferGeometry(1, 1, 1)}
    material={new MeshStandardMaterial()}
  />
</TransformControls>

The <TransformControls> component can also be used to transform an object passed to it:

Scene.svelte
<script>
  import { T } from '@threlte/core'
  import { TransformControls } from '@threlte/extras'
  import { MeshStandardMaterial, BoxBufferGeometry } from 'three'
</script>

<T.Mesh
  geometry={new BoxBufferGeometry(1, 1, 1)}
  material={new MeshStandardMaterial()}
>
  {#snippet children({ ref })}
    <TransformControls object={ref} />
  {/snippet}
</T.Mesh>

<TransformControls object={someObject} />

Component Signature

The component <TransformControls> extends both <T.TransformControls> and <T.Group>. You may pass any property of either of these components to the component <TransformControls>.

Props

name
type
required

autoPauseOrbitControls
boolean
no

autoPauseTrackballControls
boolean
no

object
THREE.Object3D
no

Bindings

name
type

controls
THREE.TransformControls

group
THREE.Group