useTimeline
Demo
Wraps Anime.js createTimeline() into a Vue composable. The timeline is created reactively — it re-creates whenever the options change — and is cancelled automatically on unmount.
Usage
Basic timeline
Chain animations on multiple elements sequentially using add.
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useTimeline } from "@juleshry/vue-animejs"
const box1 = useTemplateRef<HTMLDivElement>("box1")
const box2 = useTemplateRef<HTMLDivElement>("box2")
const { add, play, restart } = useTimeline({ autoplay: false })
add(box1, { translateX: 200, duration: 600, ease: "outExpo" })
.add(box2, { translateX: 200, duration: 600, ease: "outExpo" })
</script>
<template>
<div ref="box1" class="box" />
<div ref="box2" class="box" />
<button @click="play">Play</button>
<button @click="restart">Restart</button>
</template>Overlapping animations with position
Pass a position string to add to offset when each animation starts relative to the previous one.
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useTimeline } from "@juleshry/vue-animejs"
const box1 = useTemplateRef<HTMLDivElement>("box1")
const box2 = useTemplateRef<HTMLDivElement>("box2")
const box3 = useTemplateRef<HTMLDivElement>("box3")
const { add, play, restart } = useTimeline({ autoplay: false })
add(box1, { translateX: 200, duration: 600 })
.add(box2, { translateX: 200, duration: 600 }, "-=300" /* starts 300 ms before box1 ends */)
.add(box3, { translateX: 200, duration: 600 }, "+=100" /* starts 100 ms after box2 ends */)
</script>
<template>
<div ref="box1" class="box" />
<div ref="box2" class="box" />
<div ref="box3" class="box" />
<button @click="play">Play</button>
<button @click="restart">Restart</button>
</template>Setting initial values with set
Use set to pin a property to a value at a specific point in the timeline without animating it.
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useTimeline } from "@juleshry/vue-animejs"
const box = useTemplateRef<HTMLDivElement>("box")
const { set, play } = useTimeline({ autoplay: false })
set(box, { opacity: 0 })
.add(box, { opacity: 1, translateX: 200, duration: 800 })
</script>
<template>
<div ref="box" class="box" />
<button @click="play">Play</button>
</template>Reactive options
Put a ref straight into the options object to control timeline-level parameters reactively. The whole options object can also be a ref, a computed or a getter. When options change the timeline is recreated and all previously recorded add/set/remove/call/label/sync calls are replayed automatically.
<script setup lang="ts">
import { ref, useTemplateRef } from "vue"
import { useTimeline } from "@juleshry/vue-animejs"
const box1 = useTemplateRef<HTMLDivElement>("box1")
const box2 = useTemplateRef<HTMLDivElement>("box2")
const loop = ref<boolean>(false)
const { add, play, restart } = useTimeline({ autoplay: false, loop })
add(box1, { translateX: 200, duration: 600, ease: "outExpo" })
.add(box2, { translateX: 200, duration: 600, ease: "outExpo" }, "-=300")
</script>
<template>
<div ref="box1" class="box" />
<div ref="box2" class="box" />
<label><input v-model="loop" type="checkbox" /> Loop</label>
<button @click="play">Play</button>
<button @click="restart">Restart</button>
</template>Type Declarations
For all available options, see the Anime.js timeline documentation.
Show Type Declarations
/**
* What `add`, `set` and `remove` return: the live timeline, with its own `add` / `set` / `remove` swapped for the
* composable's queueing ones. Before mount there's no timeline yet, so only `add` / `set` / `remove` are available.
*/
export type TimelineChain = Timeline & {
/** Adds an animation to the timeline and returns a chainable object. */
add: (
targets: AnimationTargets,
params: MaybeRefOrGetter<MaybeRefOptions<AnimationParams>>,
position?: TimelinePosition | StaggerFunction<number | string>
) => TimelineChain
/** Sets a property to a value at a point in the timeline without animating it, then returns a chainable object. */
set: (
targets: AnimationTargets,
params: MaybeRefOrGetter<MaybeRefOptions<AnimationParams>>,
position?: TimelinePosition
) => TimelineChain
/** Removes an animation target (or a specific property) from the timeline and returns a chainable object. */
remove: (targets: AnimationTargets, propertyName?: string) => TimelineChain
}
export interface UseTimelineReturn {
/** The underlying Anime.js timeline instance. `undefined` until mounted. */
timeline: Readonly<ShallowRef<Timeline | undefined>>
/** Adds an animation to the timeline. Accepts a template ref or any valid Anime.js target. Returns a chainable object. */
add: (
targets: AnimationTargets,
params: MaybeRefOrGetter<MaybeRefOptions<AnimationParams>>,
position?: TimelinePosition | StaggerFunction<number | string>
) => TimelineChain
/** Sets a property to a value at a point in the timeline without animating it. Returns a chainable object. */
set: (
targets: AnimationTargets,
params: MaybeRefOrGetter<MaybeRefOptions<AnimationParams>>,
position?: TimelinePosition
) => TimelineChain
/** Removes an animation target (or a specific property) from the timeline. Returns a chainable object. */
remove: (targets: AnimationTargets, propertyName?: string) => TimelineChain
/** Synchronises another tickable (animation, timer) into the timeline at the given position. */
sync: (synced?: Tickable, position?: TimelinePosition) => Timeline | undefined
/** Adds a named label at a position so it can be referenced by `.add()` or `.seek()`. */
label: (labelName: string, position?: TimelinePosition) => Timeline | undefined
/** Inserts a callback function at a specific point in the timeline. */
call: (callback: Callback<Timer>, position?: TimelinePosition) => Timeline | undefined
/** Renders the timeline once without playing it. */
init: (internalRender?: boolean) => Timeline | undefined
/** Starts or resumes the timeline. */
play: () => Timeline | undefined
/** Reverses playback direction. */
reverse: () => Timeline | undefined
/** Pauses the timeline at the current position. */
pause: () => Timeline | undefined
/** Restarts the timeline from the beginning. */
restart: () => Timeline | undefined
/** Toggles between forward and reverse direction. */
alternate: () => Timeline | undefined
/** Resumes from a paused state. */
resume: () => Timeline | undefined
/** Jumps immediately to the end of the timeline. */
complete: () => Timeline | undefined
/** Resets the timeline to its initial state. Pass `true` for a soft reset that preserves the current cycle. */
reset: (softReset?: boolean) => Timeline | undefined
/** Stops the timeline and removes it from the Anime.js engine. */
cancel: () => Timeline | undefined
/** Cancels the timeline and restores all animated properties to their original values. */
revert: () => Timeline | undefined
/** Seeks to a specific time (in ms). */
seek: (time: number, muteCallbacks?: boolean | number, internalRender?: boolean | number) => Timeline | undefined
/** Rescales the timeline to a new total duration. */
stretch: (newDuration: number) => Timeline | undefined
/** Re-reads the current values of all animated properties from the DOM. */
refresh: () => Timeline | undefined
}
/**
* Wraps Anime.js `createTimeline()` into a Vue composable. Reactively re-creates the timeline when options change, and cancels it automatically on unmount.
*
* `add`, `set`, `remove`, `call`, `label` and `sync` calls are recorded in order: made before mount, they apply once
* the timeline exists, and when options change they're all replayed on the new timeline.
*
* @param options - Anime.js timeline parameters. Accepts a plain object, a ref / computed / getter, and refs as direct properties. Defaults to `{}`.
*/
export declare function useTimeline(options?: MaybeRefOrGetter<MaybeRefOptions<TimelineParams>>): UseTimelineReturnReactivity & Lifecycle Behavior
- The timeline is created on mount, not at
setup()time —timelineisundefineduntil then (this keepsuseTimelinesafe to call during SSR, whereonMountednever runs). Control methods other thanadd/set/call/removeare no-ops and returnundefinedwhiletimelineis unset. add,set,remove,call,labelandsynccalls are recorded in order. Made before mount, they're applied once the component mounts — safe to call at the top level of<script setup>.- If
optionschanges after mount (a new object in a ref / computed / getter, a ref inside it changing, or a property of a reactive object mutated in place), the current timeline is reverted and recreated. Every recorded call is replayed on the new timeline in the original order, so a target youremoved stays removed and labels still resolve. - The
paramsofaddandsetaccept the same shapes asoptions, but they're read when the timeline is (re)built, not watched: changing a ref inside them takes effect the next timeoptionschanges. - On component unmount, the watcher and timeline are cleaned up automatically.
TIP
add, set and remove return a TimelineChain: the live timeline, so you can chain .add() / .set() calls fluently and still reach every timeline method and property (play(), seek(), duration, ...). Before mount, only .add(), .set() and .remove() exist on it.
const { add } = useTimeline({ autoplay: false })
onMounted(() => {
add(box1, { translateX: 100, duration: 400 })
.add(box2, { translateY: 100, duration: 400 })
.add(box3, { rotate: 360, duration: 400 })
.play()
})WARNING
timeline is a readonly shallow ref. Do not mutate the Anime.js instance directly — use the returned control methods instead.