④ vue 中的動畫
阿新 • • 發佈:2022-03-16
vue 動畫
1 使用 Vue 實現基礎的 CSS 過渡與動畫效果
1.1 過渡
<style> .transition { transition: 3s background-color ease; } .blue { background: blue; } .green { background: green; } </style> <script> const app = Vue.createApp({ data() { return { animate: { transition: true, blue: true, green: false } } }, methods: { handleClick() { this.animate.blue = !this.animate.blue this.animate.green = !this.animate.green } }, template: ` <div> <div :class="animate">hello world</div> <button @click="handleClick">切換</button> </div> ` }) const vm = app.mount('#root') </script>
- 通過資料來控制元素的
DOM
和style
<style> .transition { transition: 3s background-color ease; } </style> <script> const app = Vue.createApp({ data() { return { styleObj: { background: 'blue' } } }, methods: { handleClick() { if(this.styleObj.background === 'blue') { this.styleObj.background = 'green' } else if(this.styleObj.background === 'green') { this.styleObj.background = 'blue' } } }, template: ` <div> <div class="transition" :style="styleObj">hello world</div> <button @click="handleClick">切換</button> </div> ` }) const vm = app.mount('#root') </script>
1.2 動畫
<style> @keyframes leftToRight { 0% { transform: translateX(-100px); } 50% { transform: translateX(-50px); } 0% { transform: translateX(0px); } } .animation { animation: leftToRight 3s; } </style> <script> const app = Vue.createApp({ data() { return { animate: { animation: false } } }, methods: { handleClick() { this.animate.animation = !this.animate.animation } }, template: ` <div> <div :class="animate">hello world</div> <button @click="handleClick">切換</button> </div> ` }) const vm = app.mount('#root') </script>
2 使用 transition 標籤實現單元素元件的過渡和動畫效果
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show
}
},
// <transition> --- `v-`
// <transition name='hello'> --- `hello-`
// v-if v-show
template: `
<div>
<transition>
<div v-show="show">hello world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
2.1 過渡
.v-enter-from {
opacity: 0;
}
.v-enter-to {
opacity: 1;
}
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 2s ease-in;
}
2.2 動畫
@keyframes shake {
0% {
transform: translateX(-100px);
}
50% {
transform: translateX(-50px);
}
100% {
transform: translateX(50px);
}
}
.v-enter-active,
.v-leave-active {
animation: shake 2s;
}
2.3 自定義 class 類名
<style>
@keyframes shake {
0% {
transform: translateX(-100px);
}
50% {
transform: translateX(-50px);
}
100% {
transform: translateX(50px);
}
}
.hello,
.bye {
animation: shake 2s;
}
</style>
<script>
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show
}
},
template: `
<div>
<transition
enter-active-class="hello"
leave-active-class="bye"
>
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
</script>
2.4 使用第三動畫庫 animate
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<script>
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show
}
},
template: `
<div>
<transition
enter-active-class="animate__animated animate__bounce"
leave-active-class="animate__animated animate__flash"
>
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
</script>
2.5 動畫 + 過渡
@keyframes shake {
0% {
transform: translateX(-100px);
}
50% {
transform: translateX(-50px);
}
100% {
transform: translateX(50px);
}
}
.v-enter-from {
color: red;
}
.v-enter-active {
animation: shake 2s;
transition: color 3s ease-in;
}
.v-leave-active {
color: red;
animation: shake 2s;
transition: all 3s ease-in;
}
- 動畫 & 過渡同時存在,
<transition>
新增屬性type
實現以動畫animation
| 過渡transition
的時間為準結束該過程
const app = Vue.createApp({
template: `
<div>
<transition type="transition">
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
- 動畫 & 過渡同時存在,
<transition>
新增屬性duration
實現以指定時間 (ms為單位
) 為準
const app = Vue.createApp({
template: `
<div>
<transition :duration="{ enter: 1000, leave: 3000 }">
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
2.6 通過資料來控制元素的 DOM 和 style
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show
},
handleBeforeEnter(el) {
el.style.color = "red"
},
handleEnter(el, done) {
const animation = setInterval(() => {
const color = el.style.color
if(color === 'red') {
el.style.color = 'green'
} else {
el.style.color = 'red'
}
}, 1000);
setTimeout(() => {
clearInterval(animation)
done() // 通知 handleAfterEnter
}, 5000);
},
handleAfterEnter() {
alert(123)
}
},
template: `
<div>
<transition
:css="false"
@before-enter="handleBeforeEnter"
@enter="handleEnter"
@after-enter="handleAfterEnter"
@before-leave="handleBeforeLeave"
@leave="handleLeave"
@after-leave="handleAfterLeave"
>
<div v-show="show">hello world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
3 元件和元素切換動畫的實現
3.1 多個單元素標籤之間的切換
- 動畫同時進行
<style>
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: all 3s ease-in;
}
.v-enter-to,
.v-leave-from {
opacity: 1;
}
</style>
<script>
const app = Vue.createApp({
data() {
return { show: false }
},
methods: {
handleClick() {
this.show = !this.show
}
},
template: `
<div>
<transition>
<div v-if="show">hello world</div>
<div v-else="show">bye world</div>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
</script>
1. <transition>
新增屬性 mode
實現多元素的過渡順序
-
先進場再出場:
mode="in-out"
-
先出場再進場:
mode="out-in"
2. <transition>
新增屬性 appear
實現初始動畫效果
3.2 多個單元件之間的切換
const ComponentA = {
template: '<div>hello world</div>'
}
const ComponentB = {
template: '<div>bye world</div>'
}
const app = Vue.createApp({
data() {
return { show: false }
},
methods: {
handleClick() {
this.show = !this.show
}
},
components: {
'component-a': ComponentA,
'component-b': ComponentB,
},
template: `
<div>
<transition mode="out-in" appear>
<component-a v-if="show">hello world</component-a>
<component-b v-else="show">bye world</component-b>
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
- 動態元件
const ComponentA = {
template: '<div>hello world</div>'
}
const ComponentB = {
template: '<div>bye world</div>'
}
const app = Vue.createApp({
data() {
return { component: 'component-a' }
},
methods: {
handleClick() {
if(this.component === 'component-a') {
this.component = 'component-b'
} else {
this.component = 'component-a'
}
}
},
components: {
'component-a': ComponentA,
'component-b': ComponentB,
},
template: `
<div>
<transition mode="out-in" appear>
<component :is="component" />
</transition>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
4 列表動畫
<transition-group>
<style>
.list-item {
display: inline-block;
margin-right: 10px;
}
</style>
<script>
const app = Vue.createApp({
data() {
return { list: [1, 2, 3] }
},
methods: {
handleClick() {
this.list.unshift(this.list.length + 1)
}
},
template: `
<div>
<transition-group>
<span class="list-item" v-for="item in list" :key="item">{{ item }}</span>
</transition-group>
<button @click="handleClick">切換</button>
</div>
`
})
const vm = app.mount('#root')
</script>
4.1 新增項的動畫效果
.v-enter-from {
opacity: 0;
transform: translateY(30px);
}
.v-enter-active {
transition: all 1s ease-in;
}
.v-enter-to {
opacity: 1;
transform: translateY(0);
}
4.2 所有項的動畫效果
.v-enter-from {
opacity: 0;
transform: translateY(30px);
}
.v-enter-active {
transition: all 1s ease-in;
}
.v-enter-to {
opacity: 1;
transform: translateY(0);
}
.v-move {
transition: all 1s ease-in;
}
5 狀態動畫
- 通過
資料
控制動畫
const app = Vue.createApp({
data() {
return {
number: 1,
animateNumber: 1
}
},
methods: {
handleClick() {
this.number = 10;
if(this.animateNumber < this.number) {
const animation = setInterval(() => {
this.animateNumber += 1;
if(this.animateNumber === 10) {
clearInterval(animation)
}
}, 100);
}
}
},
template: `
<div>
<span>{{ animateNumber }}</span>
<button @click="handleClick">增加</button>
</div>
`
})
const vm = app.mount('#root')