Skip to content

useDraggable ​

Demo ​

Wraps Anime.js createDraggable() into a Vue composable. The draggable instance is created reactively — it re-creates whenever the target element or options change — and is reverted automatically on unmount.

Usage ​

Basic draggable ​

vue
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useDraggable } from "@juleshry/vue-animejs"

const box = useTemplateRef("box")

const { reset, disable, enable } = useDraggable(box)
</script>

<template>
  <div ref="box" class="box" />

  <button @click="enable">Enable</button>
  <button @click="disable">Disable</button>
  <button @click="reset">Reset</button>
</template>

Constrained to a container ​

Pass a container element via the container option to keep the element within bounds. Use containerPadding to add inner spacing.

WARNING

Pass the template ref itself, not its .value: .value is still null at setup time, so container: container.value gives an unconstrained draggable. While the ref is empty, the option counts as unset. A ref to a component works too: its root element is used.

vue
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useDraggable } from "@juleshry/vue-animejs"

const box = useTemplateRef("box")
const container = useTemplateRef("container")

useDraggable(box, {
  container,
  containerPadding: 10,
})
</script>

<template>
  <div ref="container" class="stage">
    <div ref="box" class="box" />
  </div>
</template>

Release easing ​

Control the animation that plays when the element is released with releaseEase.

vue
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useDraggable } from "@juleshry/vue-animejs"

const box = useTemplateRef("box")

useDraggable(box, {
  releaseEase: "spring(1, 80, 12, 0)",
})
</script>

<template>
  <div ref="box" class="box" />
</template>

Reactive options ​

Put a ref straight into the options object to change draggable behaviour at runtime. The whole options object can also be a ref, a computed or a getter, which is what you need when a value is derived, like here, or nested (x: { snap }).

WARNING

Changing options reverts the current draggable instance and creates a new one from scratch.

vue
<script setup lang="ts">
import { useTemplateRef, ref } from "vue"
import { useDraggable } from "@juleshry/vue-animejs"

const box = useTemplateRef("box")
const locked = ref(false)

useDraggable(box, () => ({
  x: !locked.value,
  y: !locked.value,
}))
</script>

<template>
  <div ref="box" class="box" />
  <button @click="locked = !locked">Toggle lock</button>
</template>

Type Declarations ​

For all available options, see the Anime.js draggable documentation.

Show Type Declarations
ts
export interface UseDraggableReturn {
  /** The underlying Anime.js draggable instance. `undefined` until the target is available. */
  draggable: Readonly<ShallowRef<Draggable | undefined>>
  /** Disables drag interactions without destroying the instance. */
  disable: () => void
  /** Re-enables drag interactions after `disable()`. */
  enable: () => void
  /** Moves the draggable to the given x position. Pass `true` to suppress the update callback. */
  setX: (x: number, muteUpdateCallback?: boolean) => void
  /** Moves the draggable to the given y position. Pass `true` to suppress the update callback. */
  setY: (y: number, muteUpdateCallback?: boolean) => void
  /** Animates the draggable into the visible viewport. */
  animateInView: (duration?: number, gap?: number, ease?: EasingParam) => void
  /** Scrolls the draggable into the visible viewport. */
  scrollInView: (duration?: number, gap?: number, ease?: EasingParam) => void
  /** Stops any in-progress snap or momentum animation. */
  stop: () => void
  /** Resets the draggable position to its initial state. */
  reset: () => void
  /** Cancels the draggable and restores the element to its original state. */
  revert: () => void
  /** Re-reads the element's size and container bounds. */
  refresh: () => void
}

/**
 * Wraps Anime.js `createDraggable()` into a Vue composable. Reactively re-creates the draggable when the target or options change, and reverts it automatically on unmount.
 *
 * @param targets - The element(s) to make draggable. Accepts a template ref, a CSS selector, a DOM element, or a reactive ref to any of these.
 * @param options - Anime.js draggable parameters. Accepts a plain object, a ref / computed / getter, and refs as direct properties. Defaults to `{}`.
 */
export declare function useDraggable(
  targets: MaybeRef<TargetsParam>,
  options?: MaybeRefOrGetter<MaybeRefOptions<DraggableParams>>
): UseDraggableReturn

Reactivity Behavior ​

  • The draggable is created once the component has mounted, whatever form targets takes (template ref, selector, element), so a selector can point into the component's own template, and server-rendered HTML is never touched before hydration.
  • A template ref that is still empty at mount (e.g. behind a v-if) creates the draggable as soon as it resolves.
  • If either targets or options changes, the current draggable is reverted and a new one is created. For options, that means a new object in a ref / computed / getter, a ref inside it changing, or a property of a reactive object mutated in place.
  • On component unmount, the watcher and draggable instance are cleaned up automatically.

TIP

Call refresh() after any layout change that affects the container or element dimensions — for example, after a resize or after toggling visibility.

WARNING

draggable is a readonly shallow ref. Do not mutate the Anime.js instance directly — use the returned control methods instead.

Source ​

Github