|
@@ -1,7 +1,15 @@
|
|
|
-import { nextTick, reactive, ref, watch, watchEffect } from "vue";
|
|
|
-import { useCan, useMode, useStage } from "./use-global-vars";
|
|
|
+import { h, nextTick, reactive, ref, watch, watchEffect } from "vue";
|
|
|
+import {
|
|
|
+ installGlobalVar,
|
|
|
+ useCan,
|
|
|
+ useCursor,
|
|
|
+ useDownKeys,
|
|
|
+ useMode,
|
|
|
+ useStage,
|
|
|
+} from "./use-global-vars";
|
|
|
import {
|
|
|
Area,
|
|
|
+ InteractiveHook,
|
|
|
useInteractiveAreas,
|
|
|
useInteractiveDots,
|
|
|
useInteractiveProps,
|
|
@@ -18,77 +26,102 @@ import {
|
|
|
SnapPoint,
|
|
|
} from "../components";
|
|
|
import { useConversionPosition } from "./use-coversion-position";
|
|
|
-import { Pos } from "@/utils/math";
|
|
|
+import { eqPoint, lineInner, linePointLen, Pos, zeroEq } from "@/utils/math";
|
|
|
import { useCustomSnapInfos, useSnap } from "./use-snap";
|
|
|
import { generateSnapInfos } from "../components/util";
|
|
|
+import { useStore, useStoreRenderProcessors } from "../store";
|
|
|
+import DrawShape from "../renderer/draw-shape.vue";
|
|
|
+import { useHistory, useHistoryAttach } from "./use-history";
|
|
|
+import penA from "../assert/cursor/pic_pen_a.ico";
|
|
|
+import penR from "../assert/cursor/pic_pen_r.ico";
|
|
|
|
|
|
-export type AddMessageData<T extends ShapeType> = ComponentValue<
|
|
|
- T,
|
|
|
- "addMode"
|
|
|
-> extends "area"
|
|
|
+type PayData<T extends ShapeType> = ComponentValue<T, "addMode"> extends "area"
|
|
|
? Area
|
|
|
: Pos;
|
|
|
|
|
|
-export const useInteractiveAddShapeAPI = () => {
|
|
|
+export enum MessageAction {
|
|
|
+ add,
|
|
|
+ delete,
|
|
|
+ update,
|
|
|
+ replace,
|
|
|
+}
|
|
|
+
|
|
|
+export type AddMessage<T extends ShapeType> = {
|
|
|
+ consumed: PayData<T>[];
|
|
|
+ cur?: PayData<T>;
|
|
|
+ ndx?: number;
|
|
|
+ action: MessageAction;
|
|
|
+};
|
|
|
+
|
|
|
+export const useInteractiveAddShapeAPI = installGlobalVar(() => {
|
|
|
const mode = useMode();
|
|
|
const can = useCan();
|
|
|
const interactiveProps = useInteractiveProps();
|
|
|
const conversion = useConversionPosition(true);
|
|
|
|
|
|
- let quitHook: null | (() => void) = null;
|
|
|
+ let isEnter = false;
|
|
|
+ const enter = () => {
|
|
|
+ if (!isEnter) {
|
|
|
+ isEnter = true;
|
|
|
+ mode.push(Mode.add);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const leave = () => {
|
|
|
+ if (isEnter) {
|
|
|
+ isEnter = false;
|
|
|
+ mode.pop();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return {
|
|
|
addShape: <T extends ShapeType>(
|
|
|
shapeType: T,
|
|
|
preset: Partial<DrawItem<T>> = {},
|
|
|
- data: AddMessageData<T>,
|
|
|
+ data: PayData<T>,
|
|
|
pixel = false
|
|
|
) => {
|
|
|
if (!can.addMode) {
|
|
|
throw "当前状态不允许添加";
|
|
|
}
|
|
|
- mode.push(Mode.add);
|
|
|
+ enter();
|
|
|
if (pixel) {
|
|
|
data = (
|
|
|
Array.isArray(data) ? data.map(conversion) : conversion(data)
|
|
|
- ) as AddMessageData<T>;
|
|
|
+ ) as PayData<T>;
|
|
|
}
|
|
|
interactiveProps.value = {
|
|
|
type: shapeType,
|
|
|
preset,
|
|
|
- callback: () => {
|
|
|
- mode.pop();
|
|
|
- },
|
|
|
+ callback: leave,
|
|
|
operate: { single: true, immediate: true, data },
|
|
|
};
|
|
|
},
|
|
|
- enterMouseAddShape: <T extends ShapeType>(
|
|
|
+ enterMouseAddShape: async <T extends ShapeType>(
|
|
|
shapeType: T,
|
|
|
preset: Partial<DrawItem<T>> = {},
|
|
|
single = false
|
|
|
) => {
|
|
|
+ if (isEnter) {
|
|
|
+ leave();
|
|
|
+ await new Promise((resolve) => setTimeout(resolve, 16));
|
|
|
+ }
|
|
|
if (!can.addMode || mode.include(Mode.add)) {
|
|
|
throw "当前状态不允许添加";
|
|
|
}
|
|
|
- mode.push(Mode.add);
|
|
|
- quitHook = () => {
|
|
|
- mode.pop();
|
|
|
- quitHook = null
|
|
|
- }
|
|
|
+ enter();
|
|
|
interactiveProps.value = {
|
|
|
type: shapeType,
|
|
|
preset,
|
|
|
operate: { single },
|
|
|
- callback: quitHook,
|
|
|
+ callback: leave,
|
|
|
};
|
|
|
},
|
|
|
quitMouseAddShape: () => {
|
|
|
- if (quitHook) {
|
|
|
- mode.pop();
|
|
|
- }
|
|
|
+ leave();
|
|
|
interactiveProps.value = void 0;
|
|
|
},
|
|
|
};
|
|
|
-};
|
|
|
+});
|
|
|
|
|
|
export const useIsAddRunning = (shapeType?: ShapeType) => {
|
|
|
const stage = useStage();
|
|
@@ -161,205 +194,349 @@ const usePointBeforeHandler = (enableTransform = false, enableSnap = false) => {
|
|
|
};
|
|
|
};
|
|
|
|
|
|
-// 拖拽面积确定组件
|
|
|
-export const useInteractiveAddAreas = <T extends ShapeType>(
|
|
|
- type: T,
|
|
|
- refSelf = true
|
|
|
-) => {
|
|
|
+const useInteractiveAddTemp = <T extends ShapeType>({
|
|
|
+ type,
|
|
|
+ useIA,
|
|
|
+ refSelf,
|
|
|
+ enter,
|
|
|
+ quit,
|
|
|
+}: {
|
|
|
+ type: T;
|
|
|
+ useIA: InteractiveHook;
|
|
|
+ refSelf?: boolean;
|
|
|
+ enter?: () => void;
|
|
|
+ quit?: () => void;
|
|
|
+}) => {
|
|
|
const { quitMouseAddShape } = useInteractiveAddShapeAPI();
|
|
|
const isRuning = useIsAddRunning(type);
|
|
|
- const obj = components[type] as Components[T];
|
|
|
const items = reactive([]) as DrawItem<T>[];
|
|
|
- const viewItems = reactive([]) as DrawItem<T>[];
|
|
|
+ const obj = components[type] as Components[T];
|
|
|
const beforeHandler = usePointBeforeHandler(true, true);
|
|
|
+ const processors = useStoreRenderProcessors();
|
|
|
+ const store = useStore();
|
|
|
+ const processorIds = processors.register(() => DrawShape);
|
|
|
const clear = () => {
|
|
|
beforeHandler.clear();
|
|
|
beforeHandler.clearRef();
|
|
|
};
|
|
|
|
|
|
- const interactive = useInteractiveAreas({
|
|
|
+ const ia = useIA({
|
|
|
shapeType: type,
|
|
|
isRuning,
|
|
|
quit: () => {
|
|
|
+ items.length = 0;
|
|
|
+ processorIds.length = 0;
|
|
|
quitMouseAddShape();
|
|
|
clear();
|
|
|
+ quit && quit();
|
|
|
},
|
|
|
+ enter,
|
|
|
beforeHandler: (p) => {
|
|
|
beforeHandler.clear();
|
|
|
return beforeHandler.transform(p);
|
|
|
},
|
|
|
});
|
|
|
|
|
|
+ const addItem = (cur: PayData<T>) => {
|
|
|
+ let item: any = obj.interactiveToData(
|
|
|
+ {
|
|
|
+ consumed: ia.consumedMessage,
|
|
|
+ cur,
|
|
|
+ action: MessageAction.add,
|
|
|
+ } as any,
|
|
|
+ ia.preset
|
|
|
+ );
|
|
|
+ if (!item) return;
|
|
|
+ item = reactive(item);
|
|
|
+
|
|
|
+ if (ia.singleDone.value) {
|
|
|
+ store.addItem(type, item);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ items.push(item);
|
|
|
+
|
|
|
+ // 箭头参考自身位置
|
|
|
+ if (refSelf && Array.isArray(cur)) {
|
|
|
+ beforeHandler.addRef(cur[0]);
|
|
|
+ }
|
|
|
+
|
|
|
+ const stop = mergeFuns(
|
|
|
+ // 监听位置变化
|
|
|
+ watch(
|
|
|
+ cur,
|
|
|
+ () =>
|
|
|
+ obj.interactiveFixData(item, {
|
|
|
+ consumed: ia.consumedMessage,
|
|
|
+ cur,
|
|
|
+ action: MessageAction.update,
|
|
|
+ } as any),
|
|
|
+ { deep: true }
|
|
|
+ ),
|
|
|
+ // 监听是否消费完毕
|
|
|
+ watch(ia.singleDone, () => {
|
|
|
+ processorIds.push(item.id);
|
|
|
+ store.addItem(type, item);
|
|
|
+ const ndx = items.indexOf(item);
|
|
|
+ items.splice(ndx, 1);
|
|
|
+ clear();
|
|
|
+ stop();
|
|
|
+ })
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
// 每次拽结束都加组件
|
|
|
watch(
|
|
|
- () => interactive.messages,
|
|
|
- (areas) => {
|
|
|
- if (areas.length === 0) return;
|
|
|
- for (const area of areas) {
|
|
|
- let item: any = obj.interactiveToData({ area }, interactive.preset);
|
|
|
- if (!item) continue;
|
|
|
- const ndx = viewItems.length;
|
|
|
- viewItems[ndx] = item = reactive(item);
|
|
|
-
|
|
|
- if (interactive.singleDone.value) continue;
|
|
|
- if (refSelf) {
|
|
|
- beforeHandler.addRef(area[0]);
|
|
|
- }
|
|
|
- const stop = mergeFuns(
|
|
|
- watch(area, () => obj.interactiveFixData(item, { area }), {
|
|
|
- deep: true,
|
|
|
- }),
|
|
|
- watch(
|
|
|
- () => [interactive.singleDone.value, interactive.isRunning.value],
|
|
|
- () => {
|
|
|
- items[ndx] = viewItems[ndx];
|
|
|
- clear();
|
|
|
- stop();
|
|
|
- }
|
|
|
- )
|
|
|
- );
|
|
|
- }
|
|
|
- interactive.consume(areas);
|
|
|
+ () => ia.messages,
|
|
|
+ (datas: any) => {
|
|
|
+ datas.forEach(addItem);
|
|
|
+ ia.consume(datas);
|
|
|
},
|
|
|
{ immediate: true }
|
|
|
);
|
|
|
+ return items;
|
|
|
+};
|
|
|
|
|
|
- return { items, viewItems };
|
|
|
+// 拖拽面积确定组件
|
|
|
+export const useInteractiveAddAreas = <T extends ShapeType>(type: T) => {
|
|
|
+ const cursor = useCursor();
|
|
|
+ return useInteractiveAddTemp({
|
|
|
+ type,
|
|
|
+ useIA: useInteractiveAreas,
|
|
|
+ refSelf: type === "arrow",
|
|
|
+ enter() {
|
|
|
+ cursor.push("crosshair");
|
|
|
+ },
|
|
|
+ quit() {
|
|
|
+ cursor.pop();
|
|
|
+ },
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
-// 多点确定组件
|
|
|
-export const useInteractiveAddDots = <T extends ShapeType>(
|
|
|
- type: T,
|
|
|
- single = false,
|
|
|
- snap = { prev: false, next: false }
|
|
|
+export const useInteractiveAddDots = <T extends ShapeType>(type: T) => {
|
|
|
+ const cursor = useCursor();
|
|
|
+ return useInteractiveAddTemp({
|
|
|
+ type,
|
|
|
+ useIA: useInteractiveDots,
|
|
|
+ enter() {
|
|
|
+ cursor.push(penA);
|
|
|
+ },
|
|
|
+ quit() {
|
|
|
+ cursor.pop();
|
|
|
+ },
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+export const penUpdatePoints = <T extends Pos>(
|
|
|
+ transfromPoints: T[],
|
|
|
+ cur: T
|
|
|
) => {
|
|
|
+ const points = [...transfromPoints];
|
|
|
+ let oper: "del" | "add" | "set" | "no" = "add";
|
|
|
+ const resetCur = () => {
|
|
|
+ if (points.length) {
|
|
|
+ return (cur = points.pop()!);
|
|
|
+ } else {
|
|
|
+ return cur;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ let repeatStart = false;
|
|
|
+ for (let i = 0; i < points.length; i++) {
|
|
|
+ if (eqPoint(points[i], cur)) {
|
|
|
+ const isLast = i === points.length - 1;
|
|
|
+ const isStart = i === 0;
|
|
|
+
|
|
|
+ if (!isStart && !isLast) {
|
|
|
+ points.splice(i--, 1);
|
|
|
+ oper = "del";
|
|
|
+ } else if ((oper !== "del" && isLast) || isStart) {
|
|
|
+ oper = "no";
|
|
|
+ if (isStart) {
|
|
|
+ repeatStart = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (oper === "del" || oper === "no") {
|
|
|
+ if (repeatStart) {
|
|
|
+ const change = points.length > 2
|
|
|
+ return {
|
|
|
+ points,
|
|
|
+ oper,
|
|
|
+ cur: change ? cur : resetCur(),
|
|
|
+ unchanged: !change
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return { points, oper, cur: repeatStart ? cur : resetCur() };
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let i = 0, ndx = 0; i < transfromPoints.length - 1; i++, ndx++) {
|
|
|
+ const line = [transfromPoints[i], transfromPoints[i + 1]];
|
|
|
+ if (lineInner(line, cur)) {
|
|
|
+ oper = "set";
|
|
|
+ points.splice(++ndx, 0, cur);
|
|
|
+ resetCur();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return { points, oper, cur };
|
|
|
+};
|
|
|
+
|
|
|
+// 钢笔添加
|
|
|
+export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
|
|
|
const { quitMouseAddShape } = useInteractiveAddShapeAPI();
|
|
|
const isRuning = useIsAddRunning(type);
|
|
|
- const obj = components[type] as Components[T];
|
|
|
const items = reactive([]) as DrawItem<T>[];
|
|
|
- const viewItems = reactive([]) as DrawItem<T>[];
|
|
|
+ const obj = components[type] as Components[T];
|
|
|
const beforeHandler = usePointBeforeHandler(true, true);
|
|
|
+ const history = useHistory();
|
|
|
+ const processors = useStoreRenderProcessors();
|
|
|
+ const store = useStore();
|
|
|
+ const downKeys = useDownKeys();
|
|
|
+ const processorIds = processors.register(() => {
|
|
|
+ return (props: any) => h(DrawShape, { ...props, show: false });
|
|
|
+ });
|
|
|
+
|
|
|
+ let prev: Pos;
|
|
|
+ let firstEntry = true;
|
|
|
+ // 可能历史空间会撤销 重做更改到正在绘制的组件
|
|
|
+ const messages = useHistoryAttach<Pos[]>(`${type}-pen`, isRuning, []);
|
|
|
|
|
|
- // 多点确定组件,
|
|
|
- const interactive = useInteractiveDots({
|
|
|
+ const currentCursor = ref(penA);
|
|
|
+ const cursor = useCursor();
|
|
|
+ const ia = useInteractiveDots({
|
|
|
shapeType: type,
|
|
|
isRuning,
|
|
|
- beforeHandler: (p) => {
|
|
|
- beforeHandler.clear();
|
|
|
- return beforeHandler.transform(p, prev, next);
|
|
|
+ enter() {
|
|
|
+ cursor.push(currentCursor.value);
|
|
|
+ watch(currentCursor, () => {
|
|
|
+ cursor.value = currentCursor.value;
|
|
|
+ });
|
|
|
},
|
|
|
quit: () => {
|
|
|
+ items.length = 0;
|
|
|
+ processorIds.length = 0;
|
|
|
quitMouseAddShape();
|
|
|
beforeHandler.clear();
|
|
|
- item = null;
|
|
|
+ cursor.pop();
|
|
|
+ },
|
|
|
+ beforeHandler: (p) => {
|
|
|
+ beforeHandler.clear();
|
|
|
+ return beforeHandler.transform(p, prev);
|
|
|
},
|
|
|
});
|
|
|
|
|
|
- let item: any;
|
|
|
- let prev: Pos, next: Pos;
|
|
|
- watch(
|
|
|
- () => interactive.messages,
|
|
|
- (dots, _) => {
|
|
|
- if (dots.length === 0) return;
|
|
|
- for (const dot of dots) {
|
|
|
- const ndx = interactive.getNdx(dot);
|
|
|
- const addNdx = single ? 0 : viewItems.length;
|
|
|
- if (!item || !single) {
|
|
|
- item = obj.interactiveToData(
|
|
|
- { dot: dots[0], ndx },
|
|
|
- interactive.preset
|
|
|
- );
|
|
|
- if (!item) continue;
|
|
|
- viewItems[addNdx] = item = reactive(item);
|
|
|
- } else {
|
|
|
- obj.interactiveFixData(item, { dot, ndx: ndx });
|
|
|
- }
|
|
|
-
|
|
|
- if (interactive.singleDone.value) continue;
|
|
|
- const stop = mergeFuns(
|
|
|
- watch(dot, () => obj.interactiveFixData(item, { dot, ndx }), {
|
|
|
- deep: true,
|
|
|
- }),
|
|
|
- watch(
|
|
|
- () => [interactive.singleDone.value, interactive.isRunning.value],
|
|
|
- () => {
|
|
|
- if (interactive.singleDone.value) {
|
|
|
- if (!single) {
|
|
|
- item = null;
|
|
|
- items[addNdx] = viewItems[addNdx];
|
|
|
- } else {
|
|
|
- items[addNdx] = JSON.parse(JSON.stringify(viewItems[addNdx]));
|
|
|
- if (snap.prev) {
|
|
|
- prev = dot;
|
|
|
- }
|
|
|
- if (snap.next) {
|
|
|
- next = next || dot;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- beforeHandler.clear();
|
|
|
- stop();
|
|
|
- }
|
|
|
- )
|
|
|
- );
|
|
|
+ const getAddMessage = (cur: Pos) => {
|
|
|
+ let consumed = messages.value;
|
|
|
+ currentCursor.value = penA;
|
|
|
+ let pen: null | ReturnType<typeof penUpdatePoints> = null;
|
|
|
+ if (!downKeys.has("Control")) {
|
|
|
+ pen = penUpdatePoints(messages.value, cur);
|
|
|
+ if (pen.oper === "del") {
|
|
|
+ currentCursor.value = penR;
|
|
|
}
|
|
|
- interactive.consume(dots);
|
|
|
+ consumed = pen.points;
|
|
|
+ cur = pen.cur;
|
|
|
}
|
|
|
- );
|
|
|
- return { items, viewItems };
|
|
|
-};
|
|
|
|
|
|
-export const useInteractiveAdd = <T extends ShapeType>(
|
|
|
- type: T,
|
|
|
- addHandler: (items: DrawItem<T>[]) => void
|
|
|
-) => {
|
|
|
- const obj = components[type];
|
|
|
- const isRuning = useIsAddRunning(type);
|
|
|
- const once = obj.addMode === "dots";
|
|
|
- const { items, viewItems } =
|
|
|
- obj.addMode === "area"
|
|
|
- ? useInteractiveAddAreas(type, type === "arrow")
|
|
|
- : useInteractiveAddDots(type, once);
|
|
|
-
|
|
|
- const snapInfos = useCustomSnapInfos();
|
|
|
- const addedItems: Record<string, ComponentSnapInfo[]> = {};
|
|
|
- watch(
|
|
|
- items as DrawItem[],
|
|
|
- (items, oldItems) => {
|
|
|
- if (!once || !oldItems) {
|
|
|
- items = items.filter((item) => !addedItems[item.id]);
|
|
|
- } else {
|
|
|
- oldItems.forEach((item) => {
|
|
|
- addedItems[item.id]?.forEach((info) => snapInfos.remove(info));
|
|
|
- delete addedItems[item.id];
|
|
|
- });
|
|
|
+ return {
|
|
|
+ pen,
|
|
|
+ consumed,
|
|
|
+ cur,
|
|
|
+ action: firstEntry ? MessageAction.add : MessageAction.replace,
|
|
|
+ } as any;
|
|
|
+ };
|
|
|
+ const pushMessages = (cur: Pos) => {
|
|
|
+ const { pen } = getAddMessage(cur);
|
|
|
+ if (pen) {
|
|
|
+ if (!pen.unchanged) {
|
|
|
+ messages.value = pen.points;
|
|
|
+ cur = pen.cur;
|
|
|
+ messages.value.push(cur);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ messages.value.push(cur);
|
|
|
+ }
|
|
|
+
|
|
|
+ return !pen?.unchanged;
|
|
|
+ };
|
|
|
|
|
|
- items.forEach((item) => {
|
|
|
- const infos = obj.getSnapInfos(item as any);
|
|
|
- infos.forEach((info) => snapInfos.add(info));
|
|
|
- addedItems[item.id] = infos;
|
|
|
- });
|
|
|
- },
|
|
|
- { deep: true }
|
|
|
- );
|
|
|
+ const addItem = (cur: PayData<T>) => {
|
|
|
+ const dot = cur as Pos;
|
|
|
+ if (messages.value.length === 0) {
|
|
|
+ firstEntry = true;
|
|
|
+ items.length = 0;
|
|
|
+ }
|
|
|
+ let item: any = items.length === 0 ? null : items[0];
|
|
|
+ if (!item) {
|
|
|
+ item = obj.interactiveToData(getAddMessage(dot), ia.preset);
|
|
|
+ if (!item) return;
|
|
|
+ items[0] = item = reactive(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ia.singleDone.value) {
|
|
|
+ store.addItem(type, item);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const update = () => {
|
|
|
+ obj.interactiveFixData(item, getAddMessage(dot));
|
|
|
+ };
|
|
|
|
|
|
+ const stop = mergeFuns(
|
|
|
+ watch(dot, update, { immediate: true, deep: true }),
|
|
|
+ watch(
|
|
|
+ messages,
|
|
|
+ () => {
|
|
|
+ if (!messages.value) return;
|
|
|
+ if (messages.value.length === 0) {
|
|
|
+ quitMouseAddShape();
|
|
|
+ } else {
|
|
|
+ update();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+ ),
|
|
|
+ // 监听是否消费完毕
|
|
|
+ watch(ia.singleDone, () => {
|
|
|
+ prev = dot;
|
|
|
+ const cItem = JSON.parse(JSON.stringify(item));
|
|
|
+ const isChange = pushMessages(dot);
|
|
|
+ if (isChange) {
|
|
|
+ if (firstEntry) {
|
|
|
+ processorIds.push(item.id);
|
|
|
+ history.preventTrack(() => store.addItem(type, cItem));
|
|
|
+ } else {
|
|
|
+ store.setItem(type, { id: item.id, value: cItem });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ beforeHandler.clear();
|
|
|
+ stop();
|
|
|
+ firstEntry = false;
|
|
|
+ })
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ // 每次拽结束都加组件
|
|
|
watch(
|
|
|
- isRuning,
|
|
|
- (isRunning) => {
|
|
|
- // 消费结束,发送添加完毕数据,未消费的则直接丢弃
|
|
|
- if (!isRunning && items.length > 0) {
|
|
|
- addHandler([...items]);
|
|
|
- }
|
|
|
- for (const key of Object.keys(addedItems)) {
|
|
|
- addedItems[key].forEach((info) => snapInfos.remove(info));
|
|
|
- delete addedItems[key];
|
|
|
- }
|
|
|
- items.length = 0;
|
|
|
- viewItems.length = 0;
|
|
|
+ () => ia.messages,
|
|
|
+ (datas: any) => {
|
|
|
+ datas.forEach(addItem);
|
|
|
+ ia.consume(datas);
|
|
|
},
|
|
|
- { flush: "pre" }
|
|
|
+ { immediate: true }
|
|
|
);
|
|
|
+ return items;
|
|
|
+};
|
|
|
|
|
|
- return viewItems;
|
|
|
+export const useInteractiveAdd = <T extends ShapeType>(type: T) => {
|
|
|
+ const obj = components[type];
|
|
|
+ if (obj.addMode === "dots") {
|
|
|
+ return useInteractiveAddPen(type);
|
|
|
+ } else if (obj.addMode === "area") {
|
|
|
+ return useInteractiveAddAreas(type);
|
|
|
+ } else {
|
|
|
+ return useInteractiveAddDots(type);
|
|
|
+ }
|
|
|
};
|