|
@@ -7,9 +7,9 @@ import {
|
|
|
useStage,
|
|
|
} from "./use-global-vars";
|
|
|
import {
|
|
|
- useGetFormalChildren,
|
|
|
useFormalLayer,
|
|
|
useHelperLayer,
|
|
|
+ useGetFormalChildren,
|
|
|
} from "./use-layer";
|
|
|
import { themeColor } from "@/constant";
|
|
|
import { dragListener } from "@/utils/event";
|
|
@@ -38,7 +38,7 @@ import { useMouseShapesStatus } from "./use-mouse-status";
|
|
|
import Icon from "../components/icon/temp-icon.vue";
|
|
|
import { Group } from "konva/lib/Group";
|
|
|
import { Component as GroupComp, GroupData } from "../components/group";
|
|
|
-import { DrawStore, useStore } from "../store";
|
|
|
+import { useStore } from "../store";
|
|
|
import { useGetShapeBelong, useOnComponentBoundChange } from "./use-component";
|
|
|
import { useHistory } from "./use-history";
|
|
|
import { isRectContained } from "@/utils/math";
|
|
@@ -47,6 +47,7 @@ import { IconData } from "../components/icon";
|
|
|
import { usePause } from "./use-pause";
|
|
|
import mitt, { Emitter } from "mitt";
|
|
|
import { components, ShapeType, shapeTypes } from "../components";
|
|
|
+import { getFlatChildren } from "@/utils/shape";
|
|
|
|
|
|
// 多选不包含分组, 只包含选中者
|
|
|
export const useSelection = installGlobalVar(() => {
|
|
@@ -63,22 +64,27 @@ export const useSelection = installGlobalVar(() => {
|
|
|
const operMode = useOperMode();
|
|
|
const selections = ref<EntityShape[]>();
|
|
|
const transformer = useTransformer();
|
|
|
+ const getShapeSelectionManage = useGetShapeSelectionManage();
|
|
|
|
|
|
- let shapeBoxs: IRect[] = [];
|
|
|
- let shapes: EntityShape[] = [];
|
|
|
+ let itemShapeBoxs: IRect[][] = [];
|
|
|
+ let itemShapes: EntityShape[][] = [];
|
|
|
|
|
|
const updateSelections = () => {
|
|
|
const boxRect = box.getClientRect();
|
|
|
selections.value = [];
|
|
|
-
|
|
|
- for (let i = 0; i < shapeBoxs.length; i++) {
|
|
|
- if (
|
|
|
- Util.haveIntersection(boxRect, shapeBoxs[i]) &&
|
|
|
- !isRectContained(shapeBoxs[i], boxRect) &&
|
|
|
- shapes[i] !== toRaw(transformer)
|
|
|
- ) {
|
|
|
- if (!selections.value.includes(shapes[i])) {
|
|
|
- selections.value.push(shapes[i]);
|
|
|
+ for (let i = 0; i < itemShapeBoxs.length; i++) {
|
|
|
+ for (let j = 0; j < itemShapeBoxs[i].length; j++) {
|
|
|
+ const shape = itemShapes[i][j];
|
|
|
+ const box = itemShapeBoxs[i][j];
|
|
|
+ const itemSelects: EntityShape[] = [];
|
|
|
+ if (
|
|
|
+ Util.haveIntersection(boxRect, box) &&
|
|
|
+ !isRectContained(box, boxRect)
|
|
|
+ ) {
|
|
|
+ if (!selections.value.includes(shape)) {
|
|
|
+ selections.value.push(shape);
|
|
|
+ itemSelects.push(shape);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -110,8 +116,16 @@ export const useSelection = installGlobalVar(() => {
|
|
|
};
|
|
|
|
|
|
const updateInitData = () => {
|
|
|
- shapes = getChildren();
|
|
|
- shapeBoxs = shapes.map((shape) => shape.getClientRect());
|
|
|
+ itemShapes = getChildren().map((item) =>
|
|
|
+ getFlatChildren(item).filter(
|
|
|
+ (shape) =>
|
|
|
+ shape !== toRaw(transformer) &&
|
|
|
+ getShapeSelectionManage(shape)?.canSelect(shape)
|
|
|
+ )
|
|
|
+ );
|
|
|
+ itemShapeBoxs = itemShapes.map((shapes) =>
|
|
|
+ shapes.map((shape) => shape.getClientRect())
|
|
|
+ );
|
|
|
};
|
|
|
|
|
|
const stopWatch = globalWatch(
|
|
@@ -195,15 +209,15 @@ export const useShapesIcon = (
|
|
|
return [stop, pause];
|
|
|
};
|
|
|
|
|
|
-export type SelectionManageBus = Emitter<Record<"del" | "update", EntityShape>>
|
|
|
+export type SelectionManageBus = Emitter<Record<"del" | "update", EntityShape>>;
|
|
|
export type SelectionManage = {
|
|
|
- canSelect: (shape: EntityShape) => boolean;
|
|
|
+ canSelect: (shape: EntityShape, selects?: EntityShape[]) => boolean;
|
|
|
listener: (shape: EntityShape) => {
|
|
|
stop: () => void;
|
|
|
bus: SelectionManageBus;
|
|
|
};
|
|
|
};
|
|
|
-export type UseGetSelectionManage = () => SelectionManage
|
|
|
+export type UseGetSelectionManage = () => SelectionManage;
|
|
|
|
|
|
export const useStoreSelectionManage = installGlobalVar((): SelectionManage => {
|
|
|
const store = useStore();
|
|
@@ -226,29 +240,31 @@ export const useStoreSelectionManage = installGlobalVar((): SelectionManage => {
|
|
|
},
|
|
|
{ immediate: true }
|
|
|
);
|
|
|
- return { stop, bus }
|
|
|
+ return { stop, bus };
|
|
|
};
|
|
|
|
|
|
return { canSelect, listener };
|
|
|
});
|
|
|
|
|
|
export const useGetShapeSelectionManage = installGlobalVar(() => {
|
|
|
- const compManages: Partial<Record<ShapeType, SelectionManage>> = {}
|
|
|
+ const compManages: Partial<Record<ShapeType, SelectionManage>> = {};
|
|
|
for (const type of shapeTypes) {
|
|
|
- compManages[type] = components[type].useGetSelectionManage && components[type].useGetSelectionManage()
|
|
|
+ compManages[type] =
|
|
|
+ components[type].useGetSelectionManage &&
|
|
|
+ components[type].useGetSelectionManage();
|
|
|
}
|
|
|
const storeManage = useStoreSelectionManage();
|
|
|
const getShapeBelong = useGetShapeBelong();
|
|
|
return (shape: EntityShape) => {
|
|
|
- const bl = getShapeBelong(shape);
|
|
|
- if (!bl) return;
|
|
|
- const manage = bl.isSelf ? storeManage : compManages[bl.type]
|
|
|
- if (!manage) {
|
|
|
- console.log('找不到多选管理器', bl)
|
|
|
- }
|
|
|
- return manage;
|
|
|
- }
|
|
|
-})
|
|
|
+ const bl = getShapeBelong(shape);
|
|
|
+ if (!bl) return;
|
|
|
+ if (compManages[bl.type]) {
|
|
|
+ return compManages[bl.type];
|
|
|
+ } else if (bl.isSelf) {
|
|
|
+ return storeManage;
|
|
|
+ }
|
|
|
+ };
|
|
|
+});
|
|
|
|
|
|
export const useSelectionRevise = () => {
|
|
|
const getShapeSelectionManage = useGetShapeSelectionManage();
|
|
@@ -256,6 +272,12 @@ export const useSelectionRevise = () => {
|
|
|
const status = useMouseShapesStatus();
|
|
|
const store = useStore();
|
|
|
const { selections: rectSelects } = useSelection();
|
|
|
+ let selfSet = false;
|
|
|
+ const setSelectShapes = (shapes: EntityShape[]) => {
|
|
|
+ selfSet = true;
|
|
|
+ status.selects = shapes;
|
|
|
+ selfSet = false;
|
|
|
+ };
|
|
|
|
|
|
let initSelections: EntityShape[] = [];
|
|
|
watch(
|
|
@@ -266,27 +288,34 @@ export const useSelectionRevise = () => {
|
|
|
} else if (!rectSelects) {
|
|
|
initSelections = [];
|
|
|
} else {
|
|
|
- status.selects = initSelections.concat(rectSelects);
|
|
|
- filterSelect();
|
|
|
+ setSelectShapes(initSelections.concat(rectSelects));
|
|
|
}
|
|
|
}
|
|
|
);
|
|
|
useShapesIcon(computed(() => status.selects.concat(rectSelects.value || [])));
|
|
|
-
|
|
|
+
|
|
|
const filterSelect = debounce(() => {
|
|
|
- const selects: EntityShape[] = []
|
|
|
+ const selects: EntityShape[] = [];
|
|
|
for (const shape of status.selects) {
|
|
|
- const manage = getShapeSelectionManage(shape)
|
|
|
- if (manage?.canSelect(shape)) {
|
|
|
- selects.push(shape)
|
|
|
- }
|
|
|
+ const children = getFlatChildren(shape)
|
|
|
+ children.forEach(childShape => {
|
|
|
+ const manage = getShapeSelectionManage(childShape);
|
|
|
+ if (manage?.canSelect(childShape)) {
|
|
|
+ selects.push(childShape);
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
- status.selects = selects;
|
|
|
+ setSelectShapes(selects);
|
|
|
}, 16);
|
|
|
store.bus.on("delItemAfter", filterSelect);
|
|
|
store.bus.on("clearAfter", filterSelect);
|
|
|
store.bus.on("dataChangeAfter", filterSelect);
|
|
|
store.bus.on("setCurrentLayerAfter", filterSelect);
|
|
|
+ watch(
|
|
|
+ () => status.selects,
|
|
|
+ () => selfSet || filterSelect(),
|
|
|
+ { flush: "sync" }
|
|
|
+ );
|
|
|
|
|
|
const ids = computed(() => [
|
|
|
...new Set(status.selects.map((item) => item.id())),
|
|
@@ -328,7 +357,7 @@ export const useSelectionRevise = () => {
|
|
|
// data.ids;
|
|
|
},
|
|
|
onDelShape() {
|
|
|
- status.selects = [];
|
|
|
+ setSelectShapes([]);
|
|
|
},
|
|
|
onAddShape(data: GroupData) {
|
|
|
history.onceTrack(() => {
|
|
@@ -346,7 +375,7 @@ export const useSelectionRevise = () => {
|
|
|
await nextTick();
|
|
|
const $stage = stage.value!.getNode();
|
|
|
const addShape = $stage.findOne("#" + data.id) as EntityShape;
|
|
|
- status.selects = [addShape];
|
|
|
+ setSelectShapes([addShape]);
|
|
|
});
|
|
|
});
|
|
|
},
|