一、基础动画
1. 在Vue3中,动画是通过transition组件来实现的。transition组件提供了多个钩子函数,可以自定义动画的进入、离开等过渡效果。
2. 在transition组件中,可以使用`v-enter`和`v-leave`指令来定义动画进入和离开时的状态。同时也可以使用`v-enter-active`和`v-leave-active`来指定动画过渡时的状态。
3. 在动画过渡时,可以使用`.move`类名来定义动画效果的移动方向。
<transition name="fade">
<div v-if="show" class="show">Show Content</div>
</transition>
// CSS
.fade-enter-active, .fade-leave-active {
transition: opacity .3s ease-in-out;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
二、自定义动画
1. Vue3通过`defineAnimation`函数来自定义动画。`defineAnimation`函数的参数包括:名称、函数、DOM元素引用和全局上下文。
2. 在定义动画函数时,可以引入多个动画的步骤。这些动画步骤包括:enter、leave、delayEnter、delayLeave、orderEnter和orderLeave。
3. 自定义动画的步骤中,开发者可以使用动画库如Tween.js等,来完成动画过渡效果并应用到DOM元素中去。
import { defineAnimation } from 'vue'
const myAnimation = defineAnimation({
name: 'my-animation',
setup: () => {
return {
onEnter(el, done) {
anime({
targets: el,
opacity: [0, 1], // 进入时元素从透明度0到1
duration: 500,
complete: () => {
done();
}
});
},
onLeave(el, done) {
anime({
targets: el,
opacity: [1, 0], // 离开时元素从透明度1到0
duration: 500,
complete: () => {
done();
}
});
}
}
}
})
// 在组件中使用
<template>
<div v-animation="myAnimation">
Hello World
</div>
</template>
三、多元素动画
1. 在Vue3中,可以通过动画组使用多个元素的动画效果。动画组组件用于管理多个元素的动画效果,通过key的改变来触发元素的进入和离开。
2. 在动画组中,可以使用`onBeforeEnter`、`onEnter`、`onAfterEnter`等钩子函数来定义元素的进入和退出方式。
3. 在动画组中,可以使用`moveClass`属性来定义元素的移动方式。
<transition-group
name="list"
tag="ul"
move-class="move"
>
<li v-for="item in list" :key="item.id">
{{ item.text }}
</li>
</transition-group>
// CSS
.list-enter-active, .list-leave-active {
transition: transform .5s ease-in-out;
}
.move {
transform: translateX(100%);
}
四、复杂动画
1. 在Vue3中,可以通过`transition`组件和`animate`函数来实现复杂的动画效果。在`animate`函数中,可以通过执行多个动画步骤来实现动画的过渡效果。
2. 在动画步骤中,可以使用动画库如GSAP等来实现复杂的动画效果。
<template>
<transition
name="complex"
appear
mode="out-in"
@before-appear="beforeAppear"
@appear="appear"
@after-appear="afterAppear"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
>
<div :key="selected.id">
<h2>{{ selected.title }}</h2>
<p>{{ selected.content }}</p>
</div>
</transition>
</template>
<script>
import { ref } from 'vue'
import animate from '@/utils/animate'
export default {
setup() {
const selected = ref(null)
const beforeAppear = (el) => {
selected.value = { ...el.dataset }
animate.set(el, { display: 'none' })
}
const appear = (el, done) => {
animate.timeline()
.set(el, { display: 'block' }, 0)
.from(el.querySelector('h2'), {
opacity: 0,
x: -20,
duration: 0.4
}, 0.2)
.from(el.querySelector('p'), {
opacity: 0,
x: -20,
duration: 0.4,
ease: 'power2.inOut'
}, 0.4)
.call(done)
}
const afterAppear = (el) => {
animate.set(el.querySelector('h2, p'), { clearProps: 'all' })
}
const beforeEnter = (el) => {
const next = el.dataset
animate.set(el, { opacity: 0 })
animate.timeline()
.fromTo(el, {
x: 100
}, {
x: 0,
duration: 0.6,
ease: 'power2.inOut'
})
}
const enter = (el, done) => {
animate.timeline()
.fromTo(el, {
opacity: 0
}, {
opacity: 1,
duration: 0.6
})
.call(done)
}
const afterEnter = (el) => {
animate.set(el, { clearProps: 'all' })
}
const beforeLeave = (el) => {
const prev = selected.value
animate.timeline()
.fromTo(el, {
opacity: 1
}, {
opacity: 0,
duration: 0.6
})
.to(el, {
x: -100,
duration: 0.6,
ease: 'power2.inOut'
})
}
const leave = (el, done) => {
animate.set(el, {
opacity: 0
})
animate.timeline()
.fromTo(el, {
x: 0
}, {
x: -100,
duration: 0.6,
ease: 'power2.inOut'
})
.call(done)
}
const afterLeave = (el) => {
animate.set(el, { clearProps: 'all' })
}
return {
selected,
beforeAppear,
appear,
afterAppear,
beforeEnter,
enter,
afterEnter,
beforeLeave,
leave,
afterLeave
}
}
}
</script>