Skip to content

Commit

Permalink
feat: timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
= committed Dec 15, 2024
1 parent 415ea51 commit 8cdde30
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 42 deletions.
7 changes: 5 additions & 2 deletions packages/core/src/animation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,18 @@ export function defineAnimation<T, A = object>(setup: AnimationSetup<T, A>) {
export function registerAnimation<T>(
name: string,
setup: (...args: any[]) => (animate: AnimationManager<T>) => void,
relativeElapsed?: WatchSource<number>,
): void {
const current = getCurrentInstance();
const { widget } = current?.props as {
widget: T & { manager?: AnimationManager<T> };
};
if (widget) {
if (typeof widget.manager === "undefined") {
const { elapsed } = usePlayer();
widget.manager = new AnimationManager<T>(widget, elapsed);
widget.manager = new AnimationManager<T>(
widget,
relativeElapsed ?? usePlayer().elapsed,
);
}
(widget as Record<string, any>)[name] = (
...args: Parameters<typeof setup>
Expand Down
60 changes: 58 additions & 2 deletions packages/core/src/player.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { App, Ref } from "vue";
import { inject, ref } from "vue";
import { inject, ref, watch } from "vue";
import { AnimationManager } from "./animation";

const studioListenerAdded = { value: false };
Expand Down Expand Up @@ -63,7 +63,63 @@ export function usePlayer() {
}, 1000);
}

return { play, elapsed, useAnimation, setElapsed, pause, renderOnce };
function useTimeline(start: number = 0) {
const relativeElapsed = ref<number>(0);
const isPlaying = ref(false);
const localStart = ref(start);

// 监听全局时间
watch(
elapsed,
() => {
if (isPlaying.value) {
relativeElapsed.value = Math.max(0, elapsed.value - localStart.value);
}
},
{ immediate: true },
);

function play() {
isPlaying.value = true;
}

function pause() {
isPlaying.value = false;
}

function seek(time: number) {
relativeElapsed.value = time;
localStart.value = elapsed.value - time;
}

function reset() {
seek(0);
}

function useAnimation<T extends object>(widget: T) {
return new AnimationManager(widget, relativeElapsed);
}

return {
useAnimation,
elapsed: relativeElapsed,
isPlaying,
play,
pause,
seek,
reset,
};
}

return {
play,
elapsed,
useAnimation,
useTimeline,
setElapsed,
pause,
renderOnce,
};
}

export type Player = ReturnType<typeof usePlayer>;
52 changes: 14 additions & 38 deletions test/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,61 +9,37 @@ import {
Line,

Check warning on line 9 in test/src/App.vue

View workflow job for this annotation

GitHub Actions / eslint

'Line' is defined but never used
Arrow,
ArrowIns,
grow,

Check warning on line 12 in test/src/App.vue

View workflow job for this annotation

GitHub Actions / eslint

'grow' is defined but never used
move,
rotate,
} from "@vue-motion/lib";
import { onMounted } from "vue";
import { NumberPlane } from "@vue-motion/extension-math";
import { onMounted, watch } from "vue";
const rect = useWidget<RectIns>();
const line = useWidget<LineIns>();

Check warning on line 19 in test/src/App.vue

View workflow job for this annotation

GitHub Actions / eslint

'line' is assigned a value but never used
const arrow = useWidget<ArrowIns>();
const { play, elapsed } = usePlayer();
const { play, elapsed, useAnimation, useTimeline } = usePlayer();
const timeline = useTimeline(2);
onMounted(() => {
rect.move(100, 100);
// rect.rotate(180)
// rect.rotateTo(200)
// rect.zoomTo(3, 3)
rect.moveOnPath(
"M 100 100 Q 100 200 200 200 Q 300 200 300 100 Q 300 0 200 0 Q 100 0 100 100 Z",
{
by: easeInOutCirc,
},
);
rect.moveOnFunction(
(progress) => ({
x: 100 + 200 * progress,
y: 100 + 200 * progress,
}),
{
by: easeInOutCirc,
},
);
rect.parallel(
(r) => r.discolorateFillTo("skyblue"),
(r) => r.discolorateBorderTo("blue"),
(r) => r.move(-200, -200),
);
rect.exec(() => {
console.log("Hello, world!");
watch(timeline.elapsed, () => {
console.log(timeline.elapsed.value);
});
useAnimation(arrow).animate(rotate, { duration: 1, offset: 200 });
timeline
.useAnimation(rect)
.animate(move, { duration: 1, offsetX: 100, offsetY: 100 });
line.grow();
arrow.grow();
play();
document.addEventListener("click", () => {
console.log(elapsed.value);
});
timeline.play();
});
</script>

<template>
<Motion :width="1600" :height="900">
<Rect :widget="rect" :width="100" :height="100" />
<Line :widget="line" :from="[0, 0]" :to="[200, 200]" />
<!-- <Line :widget="line" :from="[0, 0]" :to="[200, 200]" /> -->
<Arrow :from="[0, 0]" :to="[-200, -200]" :widget="arrow" />
<NumberPlane :domain-x="[-5, 4]" :domain-y="[-3, 2]" :grid="true" />
</Motion>
</template>

0 comments on commit 8cdde30

Please sign in to comment.