Skip to main content
.onDragGesture(action: (state: DragGestureState) => void): Component
.onDragGesture(props: { minimumDistance?: number }, action: (state: DragGestureState) => void): Component
action
(state: DragGestureState) => void
required
A callback that receives the drag gesture state throughout the gesture lifecycle.
props
object
Configuration options for the drag gesture.

Support

Usage

Basic drag tracking

const body = () => {
    const [offset, setOffset] = useState({ x: 0, y: 0 })

    return Circle()
        .frame({ width: 60, height: 60 })
        .foregroundStyle(Color("blue"))
        .offset(offset)
        .onDragGesture((state) => {
            if (state.phase === "changed") {
                setOffset({
                    x: state.translation.x,
                    y: state.translation.y
                })
            }
            if (state.phase === "ended") {
                setOffset({ x: 0, y: 0 })
            }
        })
}

With minimum distance

Require a longer drag before recognition to avoid interfering with taps.
const body = () => {
    const [dragging, setDragging] = useState(false)

    return Rectangle()
        .frame({ width: 100, height: 100 })
        .foregroundStyle(dragging ? Color("red") : Color("blue"))
        .onDragGesture({ minimumDistance: 20 }, (state) => {
            setDragging(
                state.phase === "began" ||
                state.phase === "changed"
            )
        })
}

Swipe detection using velocity

const body = () => {
    const [direction, setDirection] = useState("")

    return Text(direction || "Swipe me")
        .frame({ width: 200, height: 200 })
        .background(Color("gray").opacity(0.2))
        .onDragGesture((state) => {
            if (state.phase === "ended") {
                if (state.velocity.x > 500) {
                    setDirection("Swiped right")
                } else if (state.velocity.x < -500) {
                    setDirection("Swiped left")
                }
            }
        })
}

Notes

  • The gesture callback fires for every phase: "possible", "began", "changed", "ended", and "cancelled".
  • translation is cumulative from the initial touch point, not a per-frame delta.
  • velocity is in points per second and is useful for flick/swipe detection.

See Also