Skip to content

Commit 19f647a

Browse files
committed
refactor: 之前的动画组件使用控制组件进行重构
1 parent 4b7adda commit 19f647a

5 files changed

Lines changed: 251 additions & 276 deletions

File tree

app/components/animate/FirstReason.vue

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
<template>
2-
<div ref="container" :style="{ opacity: 0 }" class="relative top-0 left-0 w-full h-full">
2+
<AnimateSequence
3+
ref="sequenceRef"
4+
:style="{ opacity: 0 }"
5+
class="relative top-0 left-0 w-full h-full"
6+
:init-sequence="(): AnimationSequence => [
7+
[rotateCircle, { opacity: 0, rotate: 0 }, { at: '0' }],
8+
[rotateCircle, { rotate: 0 }, { at: '0' }],
9+
['.main-intro-text', { opacity: 0, x: -50 }, { at: '0' }],
10+
[imgBox1, { opacity: 0, y: -200, x: -100, scale: 0.8 }, { at: '0' }],
11+
['.minor-intro-text', { opacity: 0, y: 50 }, { at: '0' }],
12+
]"
13+
:enter-sequence="(): AnimationSequence => [
14+
[rotateCircle, { opacity: [0, 1], x: [-100, 0] }, { duration: 0.5, at: '+0.2' }],
15+
['.main-intro-text', { opacity: [0, 1], x: [-50, 0] }, { duration: 0.4, delay: stagger(0.1), at: '+0.1' }],
16+
[imgBox1, { opacity: [0, 1], y: [-200, 0], x: [-100, -200], scale: [0.8, 1] }, { duration: 1, at: '+0' }],
17+
['.minor-intro-text', { opacity: [0, 1], y: [50, 0] }, { duration: 0.5, at: '+1' }],
18+
]"
19+
:exit-sequence="(): AnimationSequence => [
20+
['.main-intro-text', { opacity: [1, 0], x: [0, -50] }, { duration: 0.2, at: '+0.3' }],
21+
[imgBox1, { opacity: [1, 0], y: [0, -200], x: [-200, -100], scale: [1, 0.8] }, { duration: 0.3, at: '+0.1' }],
22+
[rotateCircle, { opacity: [1, 0], x: [0, -100] }, { duration: 0.5, at: '+0' }],
23+
['.minor-intro-text', { opacity: [1, 0], y: [0, 50] }, { duration: 0.2, at: '<' }],
24+
[{ opacity: [1, 0] }, { duration: 0.3, at: '+1' }],
25+
]"
26+
27+
:enter-delay="5000"
28+
:exit-delay="3000"
29+
30+
@init-complete="console.log('Init Complete')"
31+
@enter-start="() => {
32+
console.log('Enter Start')
33+
animate(rotateCircle!, { rotate: 360 }, { duration: 15, ease: 'linear', repeat: Infinity });
34+
}"
35+
@enter-complete="console.log('Enter Complete')"
36+
@exit-start="console.log('Exit Start')"
37+
@exit-complete="console.log('Exit Complete'); emit('onComplete')"
38+
>
339
<div ref="rotateCircle" class="absolute -left-[30%] -top-[10%] w-96 h-96 border-6 border-dashed border-blue-300 rounded-full" />
440
<h1 class="main-intro-text absolute left-[5%] top-[20%] w-80 h-auto">
541
{{ title1 }}
@@ -13,11 +49,13 @@
1349
<span class="minor-intro-text absolute left-[5%] top-[70%] w-80 h-auto">
1450
{{ description }}
1551
</span>
16-
</div>
52+
</AnimateSequence>
1753
</template>
1854

1955
<script setup lang="ts">
56+
import type { AnimationSequence } from 'motion-v';
2057
import { animate, stagger } from 'motion-v';
58+
import AnimateSequence from './AnimateSequence.vue';
2159
2260
defineProps<{
2361
title1: string;
@@ -28,53 +66,24 @@ const emit = defineEmits<{
2866
(e: 'onComplete'): void;
2967
}>();
3068
31-
const container = ref<HTMLElement>();
69+
const sequenceRef = ref<InstanceType<typeof AnimateSequence>>();
3270
const rotateCircle = ref<HTMLElement>();
3371
const imgBox1 = ref<HTMLElement>();
3472
35-
async function InitSequence() {
36-
const seq = [
37-
[container.value!, { opacity: 0, y: '100vh' }, { at: '0' }],
38-
[rotateCircle.value!, { opacity: 0, rotate: 0 }, { at: '<' }],
39-
[rotateCircle.value!, { rotate: 0 }, { at: '<' }],
40-
['.main-intro-text-1', { opacity: 0, x: -50 }, { at: '<' }],
41-
[imgBox1.value!, { opacity: 0, y: -200, x: -100, scale: 0.8 }, { at: '<' }],
42-
['.minor-intro-text-1', { opacity: 0, y: 50 }, { at: '<' }],
43-
];
44-
await animate(seq as any, { defaultTransition: { duration: 0.001 } });
45-
46-
// console.log('Initialized');
47-
}
48-
49-
async function runSequence() {
50-
animate(rotateCircle.value!, { rotate: 360 }, { duration: 15, ease: 'linear', repeat: Infinity });
51-
const seq = [
52-
53-
[container.value!, { opacity: [0, 1], y: ['100vh', 0] }, { duration: 1 }],
54-
55-
[rotateCircle.value!, { opacity: [0, 1] }, { duration: 0.1, at: '+0.3' }],
56-
57-
['.main-intro-text', { opacity: [0, 1], x: [-50, 0] }, { duration: 0.4, delay: stagger(0.1), at: '+0.3' }],
58-
59-
[imgBox1.value!, { opacity: [0, 1], y: [-200, 0], x: [-100, -200], scale: [0.8, 1] }, { duration: 1, at: '<' }],
60-
61-
['.minor-intro-text', { opacity: [0, 1], y: [50, 0] }, { duration: 0.5, at: '+0.1' }],
62-
63-
[container.value!, { opacity: [1, 0], y: [0, '-50vh'] }, { duration: 1, at: '+2' }],
64-
];
65-
66-
await animate(seq as any);
67-
// console.log('First sequence completed');
68-
}
69-
70-
async function runAnimate() {
71-
await InitSequence();
72-
await runSequence();
73-
emit('onComplete');
74-
}
75-
76-
onMounted(() => {
77-
runAnimate();
73+
defineExpose({
74+
playInit: async () => {
75+
sequenceRef.value?.runInitSequence();
76+
},
77+
playEnter: async () => {
78+
sequenceRef.value?.runEnterSequence();
79+
},
80+
playExit: async () => {
81+
sequenceRef.value?.runExitSequence();
82+
},
83+
runFull: async () => {
84+
await sequenceRef.value?.runFullSequence();
85+
},
86+
getStatus: () => sequenceRef.value?.aniStatus,
7887
});
7988
</script>
8089

app/components/animate/SecondReason.vue

Lines changed: 85 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,86 @@
11
<template>
2-
<div ref="container" :style="{ opacity: 0 }" class="relative top-0.5 left-0 w-full h-full">
3-
<svg
4-
class="absolute inset-0 w-full h-full"
5-
viewBox="0 0 100 100"
6-
preserveAspectRatio="none"
7-
>
8-
<path
9-
ref="line1"
10-
d="M -10 30 L 110 0"
11-
stroke="#95d1f9"
12-
stroke-width="12"
13-
fill="none"
14-
/>
15-
<path
16-
ref="line2"
17-
d="M -10 50 L 110 20"
18-
stroke="#95d1f9"
19-
stroke-width="12"
20-
fill="none"
21-
/>
22-
<path
23-
ref="line3"
24-
d="M -10 80 L 110 50"
25-
stroke="#95d1f9"
26-
stroke-width="12"
27-
fill="none"
28-
/>
29-
</svg>
30-
<h1 class="main-intro-text absolute left-[5%] top-[60%] z-10">
31-
{{ title1 }}
32-
</h1>
33-
<h1 class="main-intro-text absolute left-[20%] top-[65%] z-10">
34-
{{ title2 }}
35-
</h1>
36-
<div ref="imgBox1" class="absolute w-[95%] h-90 z-1 left-[2%] top-[20%] bg-blue-200 rounded-3xl text-center">
37-
一个占位用的,以后存放图片
2+
<AnimateSequence
3+
ref="sequenceRef"
4+
:style="{ opacity: 0 }"
5+
class="relative top-0 left-0 w-full h-full"
6+
:init-sequence="(): AnimationSequence => [
7+
[line1, { opacity: 0, pathLength: 0 }, { at: '0' }],
8+
[line2, { opacity: 0, pathLength: 0 }, { at: '0' }],
9+
[line3, { opacity: 0, pathLength: 0 }, { at: '0' }],
10+
[imgBox1, { opacity: 0, y: -200, scale: 0.4 }, { at: '0' }],
11+
['.main-intro-text', { opacity: 0, x: -50 }, { at: '0' }],
12+
['.minor-intro-text', { opacity: 0, y: 50 }, { at: '0' }],
13+
]"
14+
:enter-sequence="(): AnimationSequence => [
15+
[line1, { opacity: [0, 1], pathLength: [0, 1] }, { duration: 0.5 }],
16+
[line2, { opacity: [0, 1], pathLength: [0, 1] }, { duration: 0.5, at: '-0.3' }],
17+
[line3, { opacity: [0, 1], pathLength: [0, 1] }, { duration: 0.5, at: '-0.3' }],
18+
[imgBox1, { opacity: [0, 1], y: [-200, 0], scale: [0.4, 1] }, { duration: 1, at: '<' }],
19+
['.main-intro-text', { opacity: [0, 1], x: [-50, 0] }, { duration: 0.4, delay: stagger(0.1), at: '+0.3', type: 'spring' }],
20+
['.minor-intro-text', { opacity: [0, 1], y: [50, 0] }, { duration: 0.5, at: '+0.1', type: 'spring' }],
21+
]"
22+
:exit-sequence="(): AnimationSequence => [
23+
[line1, { opacity: [1, 0], pathLength: [1, 0] }, { duration: 0.5, at: '+0' }],
24+
[line2, { opacity: [1, 0], pathLength: [1, 0] }, { duration: 0.5, at: '+0.1' }],
25+
[line3, { opacity: [1, 0], pathLength: [1, 0] }, { duration: 0.5, at: '+0.2' }],
26+
['.main-intro-text', { opacity: [1, 0], x: [0, -50] }, { duration: 0.3, at: '+0.3' }],
27+
[imgBox1, { opacity: [1, 0], y: [0, -200], scale: [1, 0.4] }, { duration: 0.3, at: '+0.1' }],
28+
['.minor-intro-text', { opacity: [1, 0], y: [0, 50] }, { duration: 0.3, at: '+0.2' }],
29+
]"
30+
@init-complete="console.log('Init Complete')"
31+
@enter-start="() => console.log('Enter Start')"
32+
@enter-complete="console.log('Enter Complete')"
33+
@exit-start="console.log('Exit Start')"
34+
@exit-complete="console.log('Exit Complete'); emit('onComplete')"
35+
>
36+
<div ref="container" class="relative top-0.5 left-0 w-full h-full">
37+
<svg
38+
class="absolute inset-0 w-full h-full"
39+
viewBox="0 0 100 100"
40+
preserveAspectRatio="none"
41+
>
42+
<path
43+
ref="line1"
44+
d="M -10 30 L 110 0"
45+
stroke="#95d1f9"
46+
stroke-width="12"
47+
fill="none"
48+
/>
49+
<path
50+
ref="line2"
51+
d="M -10 50 L 110 20"
52+
stroke="#95d1f9"
53+
stroke-width="12"
54+
fill="none"
55+
/>
56+
<path
57+
ref="line3"
58+
d="M -10 80 L 110 50"
59+
stroke="#95d1f9"
60+
stroke-width="12"
61+
fill="none"
62+
/>
63+
</svg>
64+
<h1 class="main-intro-text absolute left-[5%] top-[60%] z-10">
65+
{{ title1 }}
66+
</h1>
67+
<h1 class="main-intro-text absolute left-[20%] top-[65%] z-10">
68+
{{ title2 }}
69+
</h1>
70+
<div ref="imgBox1" class="absolute w-[95%] h-90 z-1 left-[2%] top-[20%] bg-blue-200 rounded-3xl text-center">
71+
一个占位用的,以后存放图片
72+
</div>
73+
<span class="minor-intro-text absolute left-[5%] top-[71%] z-10">
74+
{{ description }}
75+
</span>
3876
</div>
39-
<span class="minor-intro-text absolute left-[5%] top-[71%] z-10">
40-
{{ description }}
41-
</span>
42-
</div>
77+
</AnimateSequence>
4378
</template>
4479

4580
<script setup lang="ts">
46-
import { animate, stagger } from 'motion-v';
81+
import type { AnimationSequence } from 'motion-v';
82+
import { stagger } from 'motion-v';
83+
import AnimateSequence from './AnimateSequence.vue';
4784
4885
defineProps<{
4986
title1: string;
@@ -54,61 +91,19 @@ const emit = defineEmits<{
5491
(e: 'onComplete'): void;
5592
}>();
5693
94+
const sequenceRef = ref<InstanceType<typeof AnimateSequence>>();
5795
const container = ref<HTMLElement>();
5896
const line1 = ref<HTMLElement>();
5997
const line2 = ref<HTMLElement>();
6098
const line3 = ref<HTMLElement>();
6199
const imgBox1 = ref<HTMLElement>();
62100
63-
async function InitSequence() {
64-
const seq = [
65-
66-
[container.value!, { opacity: 0, y: '100vh' }, { at: '0' }],
67-
[line1.value!, { opacity: 0, pathLength: 0 }, { at: '<' }],
68-
[line2.value!, { opacity: 0, pathLength: 0 }, { at: '<' }],
69-
[line3.value!, { opacity: 0, pathLength: 0 }, { at: '<' }],
70-
[imgBox1.value!, { opacity: 0, y: -200, scale: 0.4 }, { at: '<' }],
71-
['.main-intro-text', { opacity: 0, x: -50 }, { at: '<' }],
72-
['.minor-intro-text', { opacity: 0, y: 50 }, { at: '<' }],
73-
74-
];
75-
await animate(seq as any, { defaultTransition: { duration: 0.001 } });
76-
77-
// console.log('Initialized');
78-
}
79-
80-
async function runSequence() {
81-
const seq = [
82-
[container.value!, { opacity: [0, 1], y: ['100vh', 0] }, { duration: 1 }],
83-
84-
[line1.value!, { opacity: [0, 1], pathLength: [0, 1] }, { duration: 0.5 }],
85-
[line2.value!, { opacity: [0, 1], pathLength: [0, 1] }, { duration: 0.5, at: '-0.3' }],
86-
[line3.value!, { opacity: [0, 1], pathLength: [0, 1] }, { duration: 0.5, at: '-0.3' }],
87-
88-
[imgBox1.value!, { opacity: [0, 1], y: [-200, 0], scale: [0.4, 1] }, { duration: 1, at: '<' }],
89-
90-
['.main-intro-text', { opacity: [0, 1], x: [-50, 0] }, { duration: 0.4, delay: stagger(0.1), at: '+0.3', type: 'spring' }],
91-
92-
['.minor-intro-text', { opacity: [0, 1], y: [50, 0] }, { duration: 0.5, at: '+0.1', type: 'spring' }],
93-
94-
[line1.value!, { opacity: [1, 0], pathLength: [1, 0] }, { duration: 0.5, at: '+3' }],
95-
[line2.value!, { opacity: [1, 0], pathLength: [1, 0] }, { duration: 0.5, at: '+0.4' }],
96-
[line3.value!, { opacity: [1, 0], pathLength: [1, 0] }, { duration: 0.5, at: '+0.3' }],
97-
[container.value!, { opacity: [1, 0], y: [0, '-50vh'] }, { duration: 1, at: '+0.05' }],
98-
];
99-
100-
await animate(seq as any);
101-
// console.log('Second sequence completed');
102-
}
103-
104-
async function runAnimate() {
105-
await InitSequence();
106-
await runSequence();
107-
emit('onComplete');
108-
}
109-
110-
onMounted(() => {
111-
runAnimate();
101+
defineExpose({
102+
playInit: async () => sequenceRef.value?.runInitSequence(),
103+
playEnter: async () => sequenceRef.value?.runEnterSequence(),
104+
playExit: async () => sequenceRef.value?.runExitSequence(),
105+
runFull: async () => await sequenceRef.value?.runFullSequence(),
106+
getStatus: () => sequenceRef.value?.aniStatus,
112107
});
113108
</script>
114109

@@ -118,7 +113,6 @@ onMounted(() => {
118113
font-size: 2.25rem;
119114
font-weight: bold;
120115
}
121-
122116
.minor-intro-text {
123117
font-size: 1rem;
124118
}

0 commit comments

Comments
 (0)