|
@@ -1,16 +1,267 @@
|
|
|
-import { AnimationModel } from "@/api";
|
|
|
-import { AnimationGroup, AnimationModel3D, SDK } from "../sdk";
|
|
|
+import {
|
|
|
+ AnimationModel,
|
|
|
+ AnimationModelAction,
|
|
|
+ AnimationModelFrame,
|
|
|
+ AnimationModelPath,
|
|
|
+} from "@/api";
|
|
|
+import {
|
|
|
+ AnimationGroup,
|
|
|
+ AnimationModel3D,
|
|
|
+ AnimationModelAction3D,
|
|
|
+ AnimationModelFrame3D,
|
|
|
+ AnimationModelPath3D,
|
|
|
+ SDK,
|
|
|
+ sdk as _sdk,
|
|
|
+} from "../sdk";
|
|
|
+import { computed, nextTick, reactive, watch, watchEffect } from "vue";
|
|
|
+import { ams } from "@/store/animation";
|
|
|
+import { mergeFuns } from "@/components/drawing/hook";
|
|
|
+import { getPathNode } from "./path";
|
|
|
|
|
|
-export let animationGroup: AnimationGroup
|
|
|
+export let animationGroup: AnimationGroup;
|
|
|
+const getAMKey = (am: AnimationModel) => am.key || am.id;
|
|
|
|
|
|
-const amMap: Record<string, AnimationModel3D> = {}
|
|
|
-export const getAM = (data: AnimationModel) => {
|
|
|
- if (data.id in amMap) {
|
|
|
- return amMap[data.id]
|
|
|
+const amMap: Record<
|
|
|
+ string,
|
|
|
+ {
|
|
|
+ am?: AnimationModel3D;
|
|
|
+ frames: Record<string, AnimationModelFrame3D>;
|
|
|
+ actions: Record<string, AnimationModelAction3D>;
|
|
|
+ paths: Record<string, AnimationModelPath3D>;
|
|
|
}
|
|
|
- amMap[data.id]
|
|
|
-}
|
|
|
+> = reactive({});
|
|
|
+export const addAM = (data: AnimationModel): Promise<AnimationModel3D> => {
|
|
|
+ const key = getAMKey(data);
|
|
|
+ const stopLoad = watch(
|
|
|
+ () => {
|
|
|
+ const exixts = ams.value.some((am) => getAMKey(am) === key);
|
|
|
+ return [key, exixts] as const;
|
|
|
+ },
|
|
|
+ ([key, exixts]) => {
|
|
|
+ if (!exixts) {
|
|
|
+ const des = amMap[key];
|
|
|
+ if (!des) return;
|
|
|
+ Object.values(des.frames || {}).forEach((frame) => frame.destory());
|
|
|
+ Object.values(des.actions || {}).forEach((frame) => frame.destory());
|
|
|
+ Object.values(des.paths || {}).forEach((frame) => frame.destory());
|
|
|
+ des.am?.destory();
|
|
|
+ delete amMap[key];
|
|
|
+ } else if (!amMap[key]) {
|
|
|
+ amMap[key] = {
|
|
|
+ frames: {},
|
|
|
+ actions: {},
|
|
|
+ paths: {},
|
|
|
+ };
|
|
|
+ animationGroup
|
|
|
+ .addAnimationModel(data)
|
|
|
+ .then((am) => (amMap[key].am = am));
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopAttrib = mergeFuns(
|
|
|
+ () =>
|
|
|
+ watchEffect(() =>
|
|
|
+ amMap[key].am?.changeVisibilityRange(
|
|
|
+ data.globalVisibility ? undefined : data.visibilityRange
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ watchEffect(() => amMap[key].am?.changeTitle(data.title)),
|
|
|
+ watchEffect(() => amMap[key].am?.visibilityTitle(data.showTitle)),
|
|
|
+ watchEffect(() => amMap[key].am?.changeFontSize(data.fontSize))
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopWatch = watch(
|
|
|
+ () => ams.value.includes(data),
|
|
|
+ (exists) => {
|
|
|
+ if (!exists) {
|
|
|
+ stopLoad();
|
|
|
+ stopAttrib();
|
|
|
+ stopWatch();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { flush: "post" }
|
|
|
+ );
|
|
|
+
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const stopWatch = watchEffect(() => {
|
|
|
+ if (amMap[key]?.am) {
|
|
|
+ resolve(amMap[key]!.am!);
|
|
|
+ nextTick(() => stopWatch());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+export const addFrame = (
|
|
|
+ data: AnimationModelFrame
|
|
|
+): Promise<AnimationModelFrame3D> => {
|
|
|
+ const am = ams.value.find((item) =>
|
|
|
+ item.frames.find(({ id }) => id === data.id)
|
|
|
+ );
|
|
|
+ if (!am) {
|
|
|
+ throw "找不到am数据";
|
|
|
+ }
|
|
|
+
|
|
|
+ const key = getAMKey(am);
|
|
|
+ const stopLoad = watch(
|
|
|
+ () => {
|
|
|
+ const exists = am.frames.some(({ id }) => id === data.id);
|
|
|
+ return [amMap[key], exists] as const;
|
|
|
+ },
|
|
|
+ ([map, exists]) => {
|
|
|
+ if (!map.am) return;
|
|
|
+ if (exists && !map.frames[data.id]) {
|
|
|
+ map.frames[data.id] = map.am.addFrame(data);
|
|
|
+ } else if (!exists && map.frames[data.id]) {
|
|
|
+ map.frames[data.id].destory();
|
|
|
+ delete map.frames[data.id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopAttrib = mergeFuns(() =>
|
|
|
+ watchEffect(() => amMap[key].frames[data.id]?.changeTime(data.time))
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopWatch = watch(
|
|
|
+ () => am.frames.includes(data),
|
|
|
+ (exists) => {
|
|
|
+ if (!exists) {
|
|
|
+ stopLoad();
|
|
|
+ stopAttrib();
|
|
|
+ stopWatch();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { flush: "post" }
|
|
|
+ );
|
|
|
+
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const stopWatch = watchEffect(() => {
|
|
|
+ if (amMap[key]?.frames[data.id]) {
|
|
|
+ resolve(amMap[key].frames[data.id]);
|
|
|
+ nextTick(() => stopWatch());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+export const addAction = (
|
|
|
+ data: AnimationModelAction
|
|
|
+): Promise<AnimationModelAction3D> => {
|
|
|
+ const am = ams.value.find((item) =>
|
|
|
+ item.actions.find(({ id }) => id === data.id)
|
|
|
+ );
|
|
|
+ if (!am) {
|
|
|
+ throw "找不到am数据";
|
|
|
+ }
|
|
|
+
|
|
|
+ const key = getAMKey(am);
|
|
|
+ const stopLoad = watch(
|
|
|
+ () => {
|
|
|
+ const exists = am.actions.some(({ id }) => id === data.id);
|
|
|
+ return [amMap[key], exists] as const;
|
|
|
+ },
|
|
|
+ ([map, exists]) => {
|
|
|
+ if (!map.am) return;
|
|
|
+ if (exists && !map.actions[data.id]) {
|
|
|
+ map.actions[data.id] = map.am.addAction(data);
|
|
|
+ } else if (!exists && map.actions[data.id]) {
|
|
|
+ map.actions[data.id].destory();
|
|
|
+ delete map.actions[data.id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopAttrib = mergeFuns(
|
|
|
+ () => watchEffect(() => amMap[key].actions[data.id]?.changeTime(data.time)),
|
|
|
+ () => watchEffect(() => amMap[key].actions[data.id]?.changeAmplitude(data.amplitude)),
|
|
|
+ () => watchEffect(() => amMap[key].actions[data.id]?.changeSpeed(data.speed)),
|
|
|
+ () => watchEffect(() => amMap[key].actions[data.id]?.changeDuration(data.duration)),
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopWatch = watch(
|
|
|
+ () => am.actions.includes(data),
|
|
|
+ (exists) => {
|
|
|
+ if (!exists) {
|
|
|
+ stopLoad();
|
|
|
+ stopAttrib();
|
|
|
+ stopWatch();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { flush: "post" }
|
|
|
+ );
|
|
|
+
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const stopWatch = watchEffect(() => {
|
|
|
+ if (amMap[key]?.actions[data.id]) {
|
|
|
+ resolve(amMap[key].actions[data.id]);
|
|
|
+ nextTick(() => stopWatch());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+export const addPath = (
|
|
|
+ data: AnimationModelPath
|
|
|
+): Promise<AnimationModelPath3D> => {
|
|
|
+ const am = ams.value.find((item) =>
|
|
|
+ item.paths.find(({ id }) => id === data.id)
|
|
|
+ );
|
|
|
+ if (!am) {
|
|
|
+ throw "找不到am数据";
|
|
|
+ }
|
|
|
+ const path = computed(() => data.pathId ? getPathNode(data.pathId) : undefined)
|
|
|
+ const key = getAMKey(am);
|
|
|
+ const stopLoad = watch(
|
|
|
+ () => {
|
|
|
+ const exists = am.paths.some(({ id }) => id === data.id);
|
|
|
+ return [amMap[key], exists, path.value] as const;
|
|
|
+ },
|
|
|
+ ([map, exists, path]) => {
|
|
|
+ if (!map.am || !path) return;
|
|
|
+ if (exists && !map.paths[data.id]) {
|
|
|
+ map.paths[data.id] = map.am.addPath({...data, path});
|
|
|
+ } else if (!exists && map.paths[data.id]) {
|
|
|
+ map.paths[data.id].destory();
|
|
|
+ delete map.paths[data.id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopAttrib = mergeFuns(
|
|
|
+ () => watchEffect(() => amMap[key].paths[data.id]?.changeTime(data.time)),
|
|
|
+ () => watchEffect(() => amMap[key].paths[data.id]?.changeReverse(data.reverse)),
|
|
|
+ () => watchEffect(() => amMap[key].paths[data.id]?.changeDuration(data.duration)),
|
|
|
+ () => watchEffect(() => amMap[key].paths[data.id]?.changePath(path.value)),
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopWatch = watch(
|
|
|
+ () => am.paths.includes(data),
|
|
|
+ (exists) => {
|
|
|
+ if (!exists) {
|
|
|
+ stopLoad();
|
|
|
+ stopAttrib();
|
|
|
+ stopWatch();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { flush: "post" }
|
|
|
+ );
|
|
|
+
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ const stopWatch = watchEffect(() => {
|
|
|
+ if (amMap[key]?.paths[data.id]) {
|
|
|
+ resolve(amMap[key].paths[data.id]);
|
|
|
+ nextTick(() => stopWatch());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
|
|
|
export const associationAnimation = (sdk: SDK, el: HTMLDivElement) => {
|
|
|
- animationGroup = sdk.createAnimationGroup()
|
|
|
-}
|
|
|
+ animationGroup = sdk.createAnimationGroup();
|
|
|
+
|
|
|
+
|
|
|
+};
|