Skip to content

Why vue-animejs?

Anime.js is a powerful animation library, but using it raw inside Vue components leads to repetitive, error-prone boilerplate. vue-animejs removes that boilerplate by wiring Anime.js directly into Vue's reactivity system and component lifecycle.

Lifecycle cleanup

Animations started in onMounted must be stopped in onUnmounted, otherwise the instance keeps running and leaking memory after the component is destroyed.

vue
<script setup lang="ts">
  import { onMounted, onUnmounted, useTemplateRef } from "vue"
  import anime from "animejs"

  const box = useTemplateRef("box")
  let animation: ReturnType<typeof anime.animate> | null = null

  onMounted(() => {
    animation = anime.animate(box.value, {
      translateX: 200,
      duration: 800,
      loop: true,
    })
  })

  // Easy to forget — and a memory leak if you do
  onUnmounted(() => {
    animation?.pause()
    animation?.remove(box.value)
  })
</script>

<template>
  <div ref="box" class="box" />
</template>
vue
<script setup lang="ts">
  import { useTemplateRef } from "vue"
  import { useAnimate } from "@juleshry/vue-animejs"

  const box = useTemplateRef("box")

  // Cleanup is automatic — no onMounted, no onUnmounted
  useAnimate(box, {
    translateX: 200,
    duration: 800,
    loop: true,
  })
</script>

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

Reactive options

Updating an animation when reactive state changes requires manually restarting the instance. With vue-animejs, any Ref or getter passed as an option is watched automatically.

vue
<script setup lang="ts">
  import { ref, watch, onMounted, onUnmounted, useTemplateRef } from "vue"
  import anime from "animejs"

  const box = useTemplateRef("box")
  const duration = ref(800)
  let animation: ReturnType<typeof anime.animate> | null = null

  function createAnimation() {
    animation?.pause()
    animation?.remove(box.value)
    if (!box.value) return
    animation = anime.animate(box.value, {
      translateX: 200,
      duration: duration.value, // raw value — won't update on its own
    })
  }

  onMounted(createAnimation)
  watch(duration, createAnimation) // manually reconnect each time
  onUnmounted(() => {
    animation?.pause()
    animation?.remove(box.value)
  })
</script>

<template>
  <input v-model.number="duration" type="range" min="200" max="2000" />
  <div ref="box" class="box" />
</template>
vue
<script setup lang="ts">
  import { ref, useTemplateRef } from "vue"
  import { useAnimate } from "@juleshry/vue-animejs"

  const box = useTemplateRef("box")
  const duration = ref(800)

  // Pass the ref directly — animation restarts whenever duration changes
  useAnimate(box, { translateX: 200, duration })
</script>

<template>
  <input v-model.number="duration" type="range" min="200" max="2000" />
  <div ref="box" class="box" />
</template>

Playback controls

Controlling an animation (play, pause, restart, seek) requires holding a reference to the Anime.js instance and calling methods on it imperatively.

vue
<script setup lang="ts">
  import { onMounted, onUnmounted, useTemplateRef } from "vue"
  import anime from "animejs"

  const box = useTemplateRef("box")
  let animation: ReturnType<typeof anime.animate> | null = null

  onMounted(() => {
    animation = anime.animate(box.value, {
      translateX: 200,
      duration: 800,
      autoplay: false,
    })
  })

  onUnmounted(() => {
    animation?.pause()
    animation?.remove(box.value)
  })
</script>

<template>
  <div ref="box" class="box" />
  <button @click="animation?.play()">Play</button>
  <button @click="animation?.pause()">Pause</button>
  <button @click="animation?.restart()">Restart</button>
</template>
vue
<script setup lang="ts">
  import { useTemplateRef } from "vue"
  import { useAnimate } from "@juleshry/vue-animejs"

  const box = useTemplateRef("box")

  const { play, pause, restart } = useAnimate(box, {
    translateX: 200,
    duration: 800,
    autoplay: false,
  })
</script>

<template>
  <div ref="box" class="box" />
  <button @click="play">Play</button>
  <button @click="pause">Pause</button>
  <button @click="restart">Restart</button>
</template>