Skip to content
This repository was archived by the owner on Jun 21, 2025. It is now read-only.

Commit 8cdde30

Browse files
author
=
committed
feat: timeline
1 parent 415ea51 commit 8cdde30

File tree

3 files changed

+77
-42
lines changed

3 files changed

+77
-42
lines changed

packages/core/src/animation.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,18 @@ export function defineAnimation<T, A = object>(setup: AnimationSetup<T, A>) {
161161
export function registerAnimation<T>(
162162
name: string,
163163
setup: (...args: any[]) => (animate: AnimationManager<T>) => void,
164+
relativeElapsed?: WatchSource<number>,
164165
): void {
165166
const current = getCurrentInstance();
166167
const { widget } = current?.props as {
167168
widget: T & { manager?: AnimationManager<T> };
168169
};
169170
if (widget) {
170171
if (typeof widget.manager === "undefined") {
171-
const { elapsed } = usePlayer();
172-
widget.manager = new AnimationManager<T>(widget, elapsed);
172+
widget.manager = new AnimationManager<T>(
173+
widget,
174+
relativeElapsed ?? usePlayer().elapsed,
175+
);
173176
}
174177
(widget as Record<string, any>)[name] = (
175178
...args: Parameters<typeof setup>

packages/core/src/player.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { App, Ref } from "vue";
2-
import { inject, ref } from "vue";
2+
import { inject, ref, watch } from "vue";
33
import { AnimationManager } from "./animation";
44

55
const studioListenerAdded = { value: false };
@@ -63,7 +63,63 @@ export function usePlayer() {
6363
}, 1000);
6464
}
6565

66-
return { play, elapsed, useAnimation, setElapsed, pause, renderOnce };
66+
function useTimeline(start: number = 0) {
67+
const relativeElapsed = ref<number>(0);
68+
const isPlaying = ref(false);
69+
const localStart = ref(start);
70+
71+
// 监听全局时间
72+
watch(
73+
elapsed,
74+
() => {
75+
if (isPlaying.value) {
76+
relativeElapsed.value = Math.max(0, elapsed.value - localStart.value);
77+
}
78+
},
79+
{ immediate: true },
80+
);
81+
82+
function play() {
83+
isPlaying.value = true;
84+
}
85+
86+
function pause() {
87+
isPlaying.value = false;
88+
}
89+
90+
function seek(time: number) {
91+
relativeElapsed.value = time;
92+
localStart.value = elapsed.value - time;
93+
}
94+
95+
function reset() {
96+
seek(0);
97+
}
98+
99+
function useAnimation<T extends object>(widget: T) {
100+
return new AnimationManager(widget, relativeElapsed);
101+
}
102+
103+
return {
104+
useAnimation,
105+
elapsed: relativeElapsed,
106+
isPlaying,
107+
play,
108+
pause,
109+
seek,
110+
reset,
111+
};
112+
}
113+
114+
return {
115+
play,
116+
elapsed,
117+
useAnimation,
118+
useTimeline,
119+
setElapsed,
120+
pause,
121+
renderOnce,
122+
};
67123
}
68124

69125
export type Player = ReturnType<typeof usePlayer>;

test/src/App.vue

Lines changed: 14 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,61 +9,37 @@ import {
99
Line,
1010
Arrow,
1111
ArrowIns,
12+
grow,
13+
move,
14+
rotate,
1215
} from "@vue-motion/lib";
13-
import { onMounted } from "vue";
14-
import { NumberPlane } from "@vue-motion/extension-math";
16+
import { onMounted, watch } from "vue";
1517
1618
const rect = useWidget<RectIns>();
1719
const line = useWidget<LineIns>();
1820
const arrow = useWidget<ArrowIns>();
1921
20-
const { play, elapsed } = usePlayer();
22+
const { play, elapsed, useAnimation, useTimeline } = usePlayer();
23+
const timeline = useTimeline(2);
2124
2225
onMounted(() => {
23-
rect.move(100, 100);
24-
// rect.rotate(180)
25-
// rect.rotateTo(200)
26-
// rect.zoomTo(3, 3)
27-
28-
rect.moveOnPath(
29-
"M 100 100 Q 100 200 200 200 Q 300 200 300 100 Q 300 0 200 0 Q 100 0 100 100 Z",
30-
{
31-
by: easeInOutCirc,
32-
},
33-
);
34-
rect.moveOnFunction(
35-
(progress) => ({
36-
x: 100 + 200 * progress,
37-
y: 100 + 200 * progress,
38-
}),
39-
{
40-
by: easeInOutCirc,
41-
},
42-
);
43-
rect.parallel(
44-
(r) => r.discolorateFillTo("skyblue"),
45-
(r) => r.discolorateBorderTo("blue"),
46-
(r) => r.move(-200, -200),
47-
);
48-
rect.exec(() => {
49-
console.log("Hello, world!");
26+
watch(timeline.elapsed, () => {
27+
console.log(timeline.elapsed.value);
5028
});
29+
useAnimation(arrow).animate(rotate, { duration: 1, offset: 200 });
30+
timeline
31+
.useAnimation(rect)
32+
.animate(move, { duration: 1, offsetX: 100, offsetY: 100 });
5133
52-
line.grow();
53-
arrow.grow();
5434
play();
55-
56-
document.addEventListener("click", () => {
57-
console.log(elapsed.value);
58-
});
35+
timeline.play();
5936
});
6037
</script>
6138

6239
<template>
6340
<Motion :width="1600" :height="900">
6441
<Rect :widget="rect" :width="100" :height="100" />
65-
<Line :widget="line" :from="[0, 0]" :to="[200, 200]" />
42+
<!-- <Line :widget="line" :from="[0, 0]" :to="[200, 200]" /> -->
6643
<Arrow :from="[0, 0]" :to="[-200, -200]" :widget="arrow" />
67-
<NumberPlane :domain-x="[-5, 4]" :domain-y="[-3, 2]" :grid="true" />
6844
</Motion>
6945
</template>

0 commit comments

Comments
 (0)