123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- import { DC, EntityShape } from "@/deconstruction";
- import {
- computed,
- EmitFn,
- isRef,
- reactive,
- Ref,
- ref,
- shallowReactive,
- watchEffect,
- } from "vue";
- import { useAutomaticData } from "./use-automatic-data";
- import { useCurrentZIndex, useZIndex } from "./use-layer";
- import { useAnimationMouseStyle } from "./use-mouse-status";
- import { components, DrawItem, ShapeType } from "../components";
- import { useMatCompTransformer, useLineTransformer } from "./use-transformer";
- import { useGetShapeCopyTransform } from "./use-copy";
- import {
- Bottom,
- Delete,
- DocumentCopy,
- Location,
- Lock,
- Top,
- Unlock,
- } from "@element-plus/icons-vue";
- import { mergeFuns, onlyId } from "@/utils/shared";
- import { Shape } from "konva/lib/Shape";
- import { Transform } from "konva/lib/Util";
- import { mergeDescribes, PropertyKeys } from "../propertys";
- import { useStore } from "../store";
- import { globalWatch } from "./use-global-vars";
- import { useAlignmentShape } from "./use-alignment";
- type Emit<T> = EmitFn<{
- updateShape: (value: T) => void;
- addShape: (value: T) => void;
- delShape: () => void;
- }>;
- export const useComponentMenus = <T extends DrawItem>(
- shape: Ref<DC<EntityShape> | undefined>,
- data: Ref<T>,
- emit: Emit<T>,
- alignment?: (data: T, mat: Transform) => void,
- copyHandler?: (transform: Transform, data: T) => T
- ) => {
- const operateMenus: Array<{
- icon?: any;
- label?: string;
- handler: () => void;
- }> = shallowReactive([]);
- // 锁定 解锁
- operateMenus.push(
- reactive({
- label: computed(() => (data.value.lock ? "解锁" : "锁定")) as any,
- icon: computed(() => (data.value.lock ? Unlock : Lock)),
- handler() {
- data.value.lock = !data.value.lock;
- emit("updateShape", { ...data.value });
- },
- })
- );
- // 置顶 置底
- const currentZIndex = useCurrentZIndex();
- operateMenus.push(
- {
- label: `置顶`,
- icon: Top,
- handler() {
- data.value.zIndex = currentZIndex.max + 1;
- emit("updateShape", { ...data.value });
- },
- },
- {
- label: `置底`,
- icon: Bottom,
- handler() {
- data.value.zIndex = currentZIndex.min - 1;
- emit("updateShape", { ...data.value });
- },
- }
- );
- if (alignment) {
- const [alignmentShape] = useAlignmentShape(shape);
- operateMenus.push({
- label: "对齐",
- async handler() {
- const mat = await alignmentShape();
- alignment(data.value, mat);
- emit("updateShape", { ...data.value });
- },
- icon: Location,
- });
- }
- if (copyHandler) {
- const getCopyTransform = useGetShapeCopyTransform(shape);
- operateMenus.push({
- label: `复制`,
- icon: DocumentCopy,
- handler() {
- const transform = getCopyTransform();
- const copyData = copyHandler(
- transform,
- JSON.parse(JSON.stringify(data.value)) as T
- );
- copyData.id = onlyId();
- emit("addShape", copyData);
- },
- });
- }
- operateMenus.push({
- label: `删除`,
- icon: Delete,
- handler() {
- emit("delShape");
- },
- });
- return operateMenus;
- };
- export type UseComponentStatusProps<
- T extends DrawItem,
- S extends EntityShape
- > = {
- emit: Emit<T>;
- type?: ShapeType;
- props: { data: T };
- alignment?: (data: T, mat: Transform) => void;
- getMouseStyle: any;
- defaultStyle: any;
- propertys: PropertyKeys;
- transformType?: "line" | "mat" | "custom";
- customTransform?: (
- callback: () => void,
- shape: Ref<DC<S> | undefined>,
- data: Ref<T>
- ) => void;
- getRepShape?: () => Shape;
- copyHandler: (transform: Transform, data: T) => T;
- };
- export const useComponentStatus = <S extends EntityShape, T extends DrawItem>(
- args: UseComponentStatusProps<T, S>
- ) => {
- const shape = ref<DC<S>>();
- const data = useAutomaticData(() => args.props.data);
- const [style] = useAnimationMouseStyle({
- data: data,
- shape,
- getMouseStyle: args.getMouseStyle,
- }) as any;
- if (args.transformType === "line") {
- useLineTransformer(
- shape as any,
- data as any,
- (newData) => args.emit("updateShape", newData as T),
- args.getRepShape as any
- );
- } else if (args.transformType === "mat") {
- useMatCompTransformer(shape, data as any, (nData) =>
- args.emit("updateShape", nData as any)
- );
- } else if (args.transformType === "custom" && args.customTransform) {
- args.customTransform(
- () => args.emit("updateShape", data.value as any),
- shape,
- data
- );
- }
- useZIndex(shape, data);
- return {
- data,
- style,
- tData: computed(() => {
- const tData = { ...args.defaultStyle, ...data.value };
- if (style) {
- Object.assign(tData, style.value);
- }
- return tData;
- }),
- shape,
- operateMenus: useComponentMenus(
- shape,
- data,
- args.emit,
- args.alignment,
- args.copyHandler
- ),
- describes: mergeDescribes(
- data,
- args.defaultStyle,
- args.propertys || []
- )
- };
- };
- export const useGetComponentData = <D extends DrawItem>() => {
- const store = useStore();
- return (shape: Ref<EntityShape | undefined> | EntityShape | undefined) =>
- computed(() => {
- shape = isRef(shape) ? shape.value : shape;
- if (!shape?.id()) return;
- return store.getItemById(shape.id()) as D;
- });
- };
- export const useComponentsAttach = <T>(
- getter: <K extends ShapeType>(type: K, data: DrawItem<K>) => T,
- types = Object.keys(components) as ShapeType[]
- ) => {
- const store = useStore();
- const attachs = reactive([]) as T[];
- const cleanups = [] as Array<() => void>;
- for (const type of types) {
- cleanups.push(
- globalWatch(
- () => store.data[type]?.map((item) => item),
- (items, _, onCleanup) => {
- if (!items) return;
- for (const item of items) {
- const attachWatchStop = watchEffect((onCleanup) => {
- const attach = getter(type, item);
- attachs.push(attach);
- onCleanup(() => {
- const ndx = attachs.indexOf(attach);
- ~ndx && attachs.splice(ndx, 1);
- });
- });
- const existsWatchStop = watchEffect(() => {
- if (!items.includes(item)) {
- attachWatchStop();
- existsWatchStop();
- }
- });
- onCleanup(() => {
- attachWatchStop();
- existsWatchStop();
- });
- }
- },
- { immediate: true }
- )
- );
- }
- return {
- attachs,
- cleanup: mergeFuns(cleanups),
- };
- };
|