useScope
Demo
Wraps Anime.js createScope() into a Vue composable. Animations added to the scope are grouped together and can be reverted or refreshed all at once; the scope itself is cleaned up automatically on unmount.
Usage
Basic usage
Call add() with a callback to run animations inside the scope. Any useRawAnimate(), createTimer(), or other Anime.js tickables created inside that callback are tracked by the scope. Calling revert() undoes all of them at once and restores the original DOM state.
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useScope, useRawAnimate } from "@juleshry/vue-animejs"
const box = useTemplateRef<HTMLDivElement>("box")
const { add, revert } = useScope({})
add(() => {
useRawAnimate(box, { translateX: 200, duration: 600, loop: true, alternate: true })
})
</script>
<template>
<div ref="box" class="box" />
<button @click="revert">Revert all</button>
</template>Scoped defaults
Pass defaults to share animation parameters across everything created inside the scope. Individual useRawAnimate() calls can still override them.
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useScope, useRawAnimate } from "@juleshry/vue-animejs"
const a = useTemplateRef<HTMLDivElement>("a")
const b = useTemplateRef<HTMLDivElement>("b")
const c = useTemplateRef<HTMLDivElement>("c")
const { add, revert, refresh } = useScope({
defaults: { ease: "outElastic(1, 0.5)", duration: 900 },
})
add(() => {
useRawAnimate(a, { translateX: 120, loop: true, alternate: true })
useRawAnimate(b, { translateX: 120, delay: 150, loop: true, alternate: true })
useRawAnimate(c, { translateX: 120, delay: 300, loop: true, alternate: true })
})
</script>
<template>
<div ref="a" class="box" />
<div ref="b" class="box" />
<div ref="c" class="box" />
<button @click="revert">Revert all</button>
<button @click="refresh">Refresh</button>
</template>refresh() re-runs all add() callbacks, recreating every tracked animation from scratch. Use it after a revert() to restart, or whenever you want to apply updated parameters.
Media query-aware scope
Use mediaQueries to register media query listeners. The scope's matches object updates automatically and refresh() is called on every change, letting you branch animation behaviour based on the user's environment — for example, to respect prefers-reduced-motion.
<script setup lang="ts">
import { useTemplateRef, ref } from "vue"
import { useScope, useRawAnimate } from "@juleshry/vue-animejs"
const box = useTemplateRef<HTMLDivElement>("box")
const isNarrow = ref(false)
const { add } = useScope({
mediaQueries: {
reducedMotion: "(prefers-reduced-motion: reduce)",
narrow: "(max-width: 768px)",
},
})
add((scope) => {
isNarrow.value = scope.matches.narrow
const duration = scope.matches.reducedMotion ? 0 : 600
const distance = scope.matches.narrow ? 80 : 200
useRawAnimate(box, { translateX: distance, duration, loop: true, alternate: true })
})
</script>
<template>
<div ref="box" class="box" />
<p>narrow: {{ isNarrow }}</p>
</template>Named methods
Use registerMethod() to attach reusable callbacks to the scope. The method is stored under scope.value.methods[name] and can be called at any time.
<script setup lang="ts">
import { useTemplateRef } from "vue"
import { useScope, useRawAnimate } from "@juleshry/vue-animejs"
const box = useTemplateRef<HTMLDivElement>("box")
const { scope, registerMethod } = useScope({})
registerMethod("bounce", () => {
useRawAnimate(box, { translateY: [-20, 0], ease: "outBounce", duration: 600 })
})
function trigger() {
scope.value.methods.bounce()
}
</script>
<template>
<div ref="box" class="box" />
<button @click="trigger">Bounce</button>
</template>Type Declarations
Show Type Declarations
export interface UseScopeReturn {
/** The underlying Anime.js `Scope` instance. */
scope: Readonly<ShallowRef<Scope | undefined>>
/** Registers an anonymous method on the scope. Queued automatically if called before mount. */
add: (method: ScopeMethod) => void
/** Registers a named method on the scope so it can be called via `scope.methods[name]()`. Queued automatically if called before mount. */
registerMethod: (methodName: string, method: ScopeMethod) => void
/** Registers a method that runs exactly once on the scope. Queued automatically if called before mount. */
addOnce: (method: ScopeMethod) => void
/** Keeps the time of another tickable (animation, timer) in sync with this scope. */
keepTime: (method: (scope: Scope) => Tickable) => void
/** Cancels the scope and reverts all animations and tickables it owns. */
revert: () => void
/** Re-reads default values and media-query breakpoints for the scope. */
refresh: () => void
}
/**
* Wraps Anime.js `createScope()` into a Vue composable. Reactively re-creates the scope when params change, replays all registered methods, and reverts it automatically on unmount.
*
* Methods added before mount are queued and replayed once the component is mounted. When `params` change, every
* method registered so far is replayed on the new scope.
*
* @param params - Anime.js scope parameters. Accepts a plain object, a ref / computed / getter, and refs as direct properties.
*/
export declare function useScope(params: MaybeRefOrGetter<MaybeRefOptions<ScopeParams>>): UseScopeReturnReactivity & Lifecycle
- The scope is created once the component has mounted —
scopeisundefineduntil then. - If
paramschanges (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 scope is reverted and a new one is created with the updated parameters. Every method registered so far throughadd(),registerMethod()andaddOnce()is replayed on the new scope, in registration order. - Calls to
add(),registerMethod(), andaddOnce()made before the component mounts are queued and executed inonMounted— so callingadd()at the top level of<script setup>is safe and idiomatic. - When
mediaQueriesare provided, the scope automatically callsrefresh()whenever a media query match changes. - On component unmount,
scope.revert()is called automatically, removing all tracked animations from the DOM.
TIP
revert() restores the DOM to its state before any animations in the scope ran — not just stops them. Use it as a clean reset rather than a pause. Follow it with refresh() to restart all animations from scratch.
WARNING
scope is a readonly shallow ref. Access the underlying Anime.js instance via scope.value for low-level operations like scope.value.methods, but prefer the composable's helper functions for normal use.