5.7.0

Drag Controls

Drag and drop 3D objects in your scene with pointer events

The Drag Controls allow you to drag and move 3D objects in your scene using pointer events. You can optionally lock movement to a single axis, set drag limits per axis, and listen to drag lifecycle events.

Usage

The objects prop accepts an array of Object3D instances. You can pass template refs directly — Vue will unwrap them automatically.

<script setup>
import { shallowRef } from 'vue'
import { DragControls } from '@tresjs/cientos'

const boxRef = shallowRef()
</script>

<template>
  <TresCanvas>
    <TresPerspectiveCamera :position="[0, 7.5, 7.5]" :look-at="[0, 0, 0]" />
    <DragControls :objects="[boxRef]" />
    <TresMesh ref="boxRef">
      <TresBoxGeometry />
      <TresMeshStandardMaterial />
    </TresMesh>
  </TresCanvas>
</template>
If you are using OrbitControls alongside DragControls, they will interfere with each other. Set make-default on OrbitControls to prevent conflicts while dragging.

Props

PropDescriptionDefault
objectsArray of Object3D instances to make draggable.[]
cameraThe camera used for raycasting. Defaults to the scene's active camera.undefined
enabledIf false, dragging is disabled and the object snaps back to its position on each drag event.true
lockLocks movement along one axis. Can be 'x', 'y', 'z', or 'none'.'none'
dragLimitsPer-axis position limits as [[xMin, xMax], [yMin, yMax] | undefined, [zMin, zMax] | undefined]. Pass undefined for axes with no limit.undefined
domElementThe DOM element that listens for pointer events.undefined

Events

EventDescriptionPayload
dragstartFired when the user starts dragging an object.ThreeDragControls
dragFired every frame while an object is being dragged.ThreeDragControls
dragendFired when the user releases a dragged object.ThreeDragControls
hoveronFired when the pointer moves over a draggable object.ThreeDragControls
hoveroffFired when the pointer leaves a draggable object.ThreeDragControls

Tip

Grid snapping

There is no built-in snap prop, but you can implement snapping in the @drag event handler by rounding the object's position to the desired interval:

<script setup>
import { shallowRef } from 'vue'
import { DragControls } from '@tresjs/cientos'

const boxRef = shallowRef()

function onDrag() {
  if (!boxRef.value) { return }
  const snap = 0.5
  boxRef.value.position.x = Math.round(boxRef.value.position.x / snap) * snap
  boxRef.value.position.z = Math.round(boxRef.value.position.z / snap) * snap
}
</script>

<template>
  <TresCanvas>
    <TresPerspectiveCamera :position="[0, 7.5, 7.5]" :look-at="[0, 0, 0]" />
    <DragControls :objects="[boxRef]" lock="y" @drag="onDrag" />
    <TresMesh ref="boxRef">
      <TresBoxGeometry />
      <TresMeshStandardMaterial />
    </TresMesh>
  </TresCanvas>
</template>