|
@@ -3,6 +3,7 @@ import {
|
|
|
AnimationModelAction,
|
|
|
AnimationModelFrame,
|
|
|
AnimationModelPath,
|
|
|
+ AnimationModelSubtitle,
|
|
|
} from "@/api";
|
|
|
import {
|
|
|
AnimationGroup,
|
|
@@ -13,10 +14,14 @@ import {
|
|
|
SDK,
|
|
|
sdk as _sdk,
|
|
|
} from "../sdk";
|
|
|
-import { computed, nextTick, reactive, watch, watchEffect } from "vue";
|
|
|
+import { computed, nextTick, reactive, ref, watch, watchEffect } from "vue";
|
|
|
import { ams } from "@/store/animation";
|
|
|
import { mergeFuns } from "@/components/drawing/hook";
|
|
|
import { getPathNode } from "./path";
|
|
|
+import { diffArrayChange, mount } from "@/utils";
|
|
|
+import { Pos } from "@/utils/event";
|
|
|
+import Subtitle from "@/components/subtitle/index.vue";
|
|
|
+import { Size } from "@/components/drawing/dec";
|
|
|
|
|
|
export let animationGroup: AnimationGroup;
|
|
|
const getAMKey = (am: AnimationModel) => am.key || am.id;
|
|
@@ -28,6 +33,7 @@ const amMap: Record<
|
|
|
frames: Record<string, AnimationModelFrame3D>;
|
|
|
actions: Record<string, AnimationModelAction3D>;
|
|
|
paths: Record<string, AnimationModelPath3D>;
|
|
|
+ subtitles: Record<string, () => void>;
|
|
|
}
|
|
|
> = reactive({});
|
|
|
export const addAM = (data: AnimationModel): Promise<AnimationModel3D> => {
|
|
@@ -51,6 +57,7 @@ export const addAM = (data: AnimationModel): Promise<AnimationModel3D> => {
|
|
|
frames: {},
|
|
|
actions: {},
|
|
|
paths: {},
|
|
|
+ subtitles: {},
|
|
|
};
|
|
|
animationGroup
|
|
|
.addAnimationModel(data)
|
|
@@ -61,12 +68,11 @@ export const addAM = (data: AnimationModel): Promise<AnimationModel3D> => {
|
|
|
);
|
|
|
|
|
|
const stopAttrib = mergeFuns(
|
|
|
- () =>
|
|
|
- watchEffect(() =>
|
|
|
- amMap[key].am?.changeVisibilityRange(
|
|
|
- data.globalVisibility ? undefined : data.visibilityRange
|
|
|
- )
|
|
|
- ),
|
|
|
+ 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))
|
|
@@ -175,10 +181,14 @@ export const addAction = (
|
|
|
);
|
|
|
|
|
|
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)),
|
|
|
+ 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(
|
|
@@ -203,7 +213,6 @@ export const addAction = (
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-
|
|
|
export const addPath = (
|
|
|
data: AnimationModelPath
|
|
|
): Promise<AnimationModelPath3D> => {
|
|
@@ -213,7 +222,9 @@ export const addPath = (
|
|
|
if (!am) {
|
|
|
throw "找不到am数据";
|
|
|
}
|
|
|
- const path = computed(() => data.pathId ? getPathNode(data.pathId) : undefined)
|
|
|
+ const path = computed(() =>
|
|
|
+ data.pathId ? getPathNode(data.pathId) : undefined
|
|
|
+ );
|
|
|
const key = getAMKey(am);
|
|
|
const stopLoad = watch(
|
|
|
() => {
|
|
@@ -223,7 +234,7 @@ export const addPath = (
|
|
|
([map, exists, path]) => {
|
|
|
if (!map.am || !path) return;
|
|
|
if (exists && !map.paths[data.id]) {
|
|
|
- map.paths[data.id] = map.am.addPath({...data, path});
|
|
|
+ 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];
|
|
@@ -232,10 +243,10 @@ export const addPath = (
|
|
|
);
|
|
|
|
|
|
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)),
|
|
|
+ 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(
|
|
@@ -260,8 +271,105 @@ export const addPath = (
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+export const addSubtitle = (data: AnimationModelSubtitle) => {
|
|
|
+ const am = ams.value.find((item) =>
|
|
|
+ item.subtitles.find(({ id }) => id === data.id)
|
|
|
+ );
|
|
|
+ if (!am) {
|
|
|
+ throw "找不到am数据";
|
|
|
+ }
|
|
|
+ const key = getAMKey(am);
|
|
|
+ const size = ref({ width: 0, height: 0 });
|
|
|
+ const show = ref(false)
|
|
|
+ const pixel = ref<Pos>();
|
|
|
+ const stopLoad = watch(
|
|
|
+ () => {
|
|
|
+ const exists = am.subtitles.some(({ id }) => id === data.id);
|
|
|
+ return [amMap[key], exists] as const;
|
|
|
+ },
|
|
|
+ ([map, exists]) => {
|
|
|
+ if (!map.am) return;
|
|
|
+ if (exists && !map.subtitles[data.id]) {
|
|
|
+ map.subtitles[data.id] = mount(
|
|
|
+ document.querySelector("#app")!,
|
|
|
+ Subtitle,
|
|
|
+ reactive({
|
|
|
+ pixel,
|
|
|
+ show,
|
|
|
+ data,
|
|
|
+ sizeChang: (csize: Size) => (size.value = csize),
|
|
|
+ })
|
|
|
+ );
|
|
|
+ } else if (!exists && map.subtitles[data.id]) {
|
|
|
+ map.subtitles[data.id]();
|
|
|
+ delete map.subtitles[data.id];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopAttrib = mergeFuns(
|
|
|
+ watch([currentTime, () => amMap[am.id].am, size], () => {
|
|
|
+ if (currentTime.value >= data.time && (data.time + data.duration) <= currentTime.value) {
|
|
|
+ amMap[am.id].am?.getCurrentSubtitlePixel(size.value)
|
|
|
+ show.value = true
|
|
|
+ } else {
|
|
|
+ show.value = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ );
|
|
|
+
|
|
|
+ const stopWatch = watch(
|
|
|
+ () => am.subtitles.includes(data),
|
|
|
+ (exists) => {
|
|
|
+ if (!exists) {
|
|
|
+ stopLoad();
|
|
|
+ stopAttrib();
|
|
|
+ stopWatch();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { flush: "post" }
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export const currentTime = ref(0);
|
|
|
export const associationAnimation = (sdk: SDK, el: HTMLDivElement) => {
|
|
|
animationGroup = sdk.createAnimationGroup();
|
|
|
|
|
|
-
|
|
|
+ watchEffect(() => {
|
|
|
+ animationGroup.setCurrentTime(currentTime.value);
|
|
|
+ });
|
|
|
+
|
|
|
+ animationGroup.bus.on('currentTime', time => currentTime.value = time)
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => [...ams.value],
|
|
|
+ (newv, oldv = []) => {
|
|
|
+ const { added } = diffArrayChange(newv, oldv);
|
|
|
+ added.forEach(addAM);
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => ams.value.flatMap((am) => am.frames),
|
|
|
+ (newv, oldv = []) => {
|
|
|
+ const { added } = diffArrayChange(newv, oldv);
|
|
|
+ added.forEach(addFrame);
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => ams.value.flatMap((am) => am.actions),
|
|
|
+ (newv, oldv = []) => {
|
|
|
+ const { added } = diffArrayChange(newv, oldv);
|
|
|
+ added.forEach(addAction);
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => ams.value.flatMap((am) => am.paths),
|
|
|
+ (newv, oldv = []) => {
|
|
|
+ const { added } = diffArrayChange(newv, oldv);
|
|
|
+ added.forEach(addPath);
|
|
|
+ }
|
|
|
+ );
|
|
|
};
|