Animation Techniques
Section titled “Animation Techniques”Vue provides the <Transition> and <TransitionGroup> components for handling enter / leave and list transitions. However, there are many other ways of using animations on the web, even in a Vue application. Here we will discuss a few additional techniques.
Class-based Animations
Section titled “Class-based Animations”For elements that are not entering / leaving the DOM, we can trigger animations by dynamically adding a CSS class:
const disabled = ref(false)
function warnDisabled() { disabled.value = true setTimeout(() => { disabled.value = false }, 1500)}<div :class="{ shake: disabled }"> <button @click="warnDisabled">Click me</button> <span v-if="disabled">This feature is disabled!</span></div>.shake { animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; transform: translate3d(0, 0, 0);}
@keyframes shake { 10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 80% { transform: translate3d(2px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(4px, 0, 0); }}State-driven Animations
Section titled “State-driven Animations”Some transition effects can be applied by interpolating values, for instance by binding a style to an element while an interaction occurs. Take this example for instance:
const x = ref(0)
function onMousemove(e) { x.value = e.clientX}<div @mousemove="onMousemove" :style="{ backgroundColor: `hsl(${x}, 80%, 50%)` }" class="movearea"> <p>Move your mouse across this div...</p> <p>x: {{ x }}</p></div>.movearea { transition: 0.3s background-color ease;}In addition to color, you can also use style bindings to animate transform, width, or height. You can even animate SVG paths using spring physics - after all, they are all attribute data bindings:
Animating with Watchers
Section titled “Animating with Watchers”With some creativity, we can use watchers to animate anything based on some numerical state. For example, we can animate the number itself:
import { ref, reactive, watch } from 'vue'import gsap from 'gsap'
const number = ref(0)const tweened = reactive({ number: 0})
// Note: For inputs greater than Number.MAX_SAFE_INTEGER (9007199254740991),// the result may be inaccurate due to limitations in JavaScript number precision.watch(number, (n) => { gsap.to(tweened, { duration: 0.5, number: Number(n) || 0 })})Type a number: <input v-model.number="number" /><p>{{ tweened.number.toFixed(0) }}</p>