03 Vue 动画
loyalvi Lv7

03 Vue动画

过渡与动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
/* 动画
@keyframes leftToRight {
0% {
transform: translateX(-100px);
}
50% {
transform: translateX(-50px);
}
0% {
transform: translateX(0px);
}
}
.animation {
animation: leftToRight 3s;
} */
/* 过渡
.transition {
transition: 3s background-color ease;
}
.blue {
background: blue;
}
.green {
background: green;
} */
.transition {
transition: 3s background-color ease;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
styleObj: {
background: 'blue'
}
}
},
methods: {
handleClick() {
if(this.styleObj.background === 'blue') {
this.styleObj.background = 'green';
}else {
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>
</html>

单元素组件过渡和动画

单元素,单组件的入场出场动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.v-enter-from{}
.v-enter-from,
.v-leave-active{
transition: 3s background-color ease;
}
.v-enter-to{}
.v-leave-to{}
/*-------动画-----*/
@keyframes shake {
0% {
transform: translateX(-100px)
}
50% {
transform: translateX(-50px)
}
100% {
transform: translateX(50px)
}
}
.v-leave-active {
animation: shake 3s;
}
.v-enter-active {
animation: shake 3s;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 单元素,单组件的入场出场动画
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<div>
<transition>
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切换</button>
</div>
`
});

transition的name命名,也可以在标签里直接重命名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
@keyframes shake {
0% {
transform: translateX(-100px)
}
50% {
transform: translateX(-50px)
}
100% {
transform: translateX(50px)
}
}
.hello-leave-active {
animation: shake 3s;
}
.hello-enter-active {
animation: shake 3s;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 单元素,单组件的入场出场动画
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show;
}
},
template: `
<div>
<transition name="hello">
<div v-if="show">hello world</div>
</transition>
<button @click="handleClick">切换</button>
</div>
`
});
const vm = app.mount('#root');
</script>
</html>

使用animate.css网站的动画Animate.css | 一个跨浏览器的 CSS 动画库。 中文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<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__bounce"
>
<div v-show="show">hello world</div>
</transition>
<button @click="handleClick">切换</button>
</div>
`
});
const vm = app.mount('#root');
</script>
</html>

过渡和动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
@keyframes shake {
0% {
transform: translateX(-100px)
}
50% {
transform: translateX(-50px)
}
100% {
transform: translateX(50px)
}
}
.v-enter-from {
color: red;
}
.v-enter-active {
animation: shake 3s;
transition: color 10s ease-in;
}
.v-leave-active {
color: red;
animation: shake 3s;
transition: all 10s ease-in;
}
</style>

transition标签使用js执行动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
const app = Vue.createApp({
data() {
return {
show: false
}
},
methods: {
handleClick() {
this.show = !this.show;
},
handleBeforeEnter(el) {
el.style.color = "red";
},
handleEnterActive(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();
}, 3000)
},
handleEnterEnd(el) {
alert(123);
}
},
template: `
<div>
<transition
:css="false"
@before-enter="handleBeforeEnter"
@enter="handleEnterActive"
@after-enter="handleEnterEnd"
>
<div v-show="show">hello world</div>
</transition>
<button @click="handleClick">切换</button>
</div>
`
});

组件和元素切换动画的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
.v-leave-to {
opacity: 0;
}
.v-enter-from {
opacity: 0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s ease-in;
}
.v-leave-from ,
.v-enter-to {
opacity: 1;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 多个单元素标签之间的切换
// 多个单组件之间的切换
//mode="out-in" 先隐藏再展示
//appear 渲染时就给动画
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');
</script>
</html>

列表动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
.v-enter-from {
opacity: 0;
transform: translateY(30px);
}
.v-enter-active {
transition: all .5s ease-in;
}
.v-enter-to {
opacity: 1;
transform: translateY(0);
}
.v-move {
transition: all .5s ease-in;
}
.list-item {
display: inline-block;
margin-right: 10px;
}
</style>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<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>
</html>

状态动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
// 状态动画
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>
<div>{{animateNumber}}</div>
<button @click="handleClick">增加</button>
</div>
`
});
const vm = app.mount('#root');
</script>
</html>
由 Hexo 驱动 & 主题 Keep
访客数 访问量