|
@@ -1,11 +1,16 @@
|
|
|
import { useMouseShapeStatus } from "./use-mouse-status.ts";
|
|
|
import { Ref, ref, watch } from "vue";
|
|
|
-import { DC, EntityShape } from "../../helper/deconstruction";
|
|
|
+import { DC, EntityShape } from "../../deconstruction";
|
|
|
import { Shape } from "konva/lib/Shape";
|
|
|
-import { installGlobalVar, useMode, useStage, useTransformIngShapes } from "./use-global-vars.ts";
|
|
|
+import {
|
|
|
+ installGlobalVar,
|
|
|
+ useMode,
|
|
|
+ useStage,
|
|
|
+ useTransformIngShapes,
|
|
|
+} from "./use-global-vars.ts";
|
|
|
import { Mode } from "../../constant/mode.ts";
|
|
|
import { Transform, Util } from "konva/lib/Util";
|
|
|
-import { Pos } from "@/utils/math.ts";
|
|
|
+import { Pos, vector } from "@/utils/math.ts";
|
|
|
import { useConversionPosition } from "./use-coversion-position.ts";
|
|
|
import { getOffset, listener } from "@/utils/event.ts";
|
|
|
import { flatPositions, mergeFuns } from "@/utils/shared.ts";
|
|
@@ -13,14 +18,16 @@ import { Line } from "konva/lib/shapes/Line";
|
|
|
import { setShapeTransform } from "@/utils/shape.ts";
|
|
|
import { TransformerConfig, Transformer } from "konva/lib/shapes/Transformer";
|
|
|
import { themeMouseColors } from "@/constant/help-style.ts";
|
|
|
-import { useAutomaticData } from "./use-automatic-data.ts";
|
|
|
+import { useSnapToPoints } from "./use-snap.ts";
|
|
|
+import { useViewerInvertTransform } from "./use-viewer.ts";
|
|
|
|
|
|
-export type TransformerExtends = Transformer & { queueShapes: Ref<EntityShape[]> }
|
|
|
-export const transformRectPadding = 10;
|
|
|
+export type TransformerExtends = Transformer & {
|
|
|
+ queueShapes: Ref<EntityShape[]>;
|
|
|
+};
|
|
|
export const useTransformer = installGlobalVar(() => {
|
|
|
- const anchorCornerRadius = 5
|
|
|
- const transformer = new Transformer({
|
|
|
- borderStrokeWidth: 2,
|
|
|
+ const anchorCornerRadius = 5;
|
|
|
+ const transformer = new Transformer({
|
|
|
+ borderStrokeWidth: 2,
|
|
|
borderStroke: themeMouseColors.pub,
|
|
|
anchorCornerRadius,
|
|
|
anchorSize: anchorCornerRadius * 2,
|
|
@@ -28,35 +35,97 @@ export const useTransformer = installGlobalVar(() => {
|
|
|
anchorStroke: themeMouseColors.pub,
|
|
|
anchorFill: themeMouseColors.press,
|
|
|
padding: 10,
|
|
|
- useSingleNodeRotation: true
|
|
|
+ useSingleNodeRotation: true,
|
|
|
}) as TransformerExtends;
|
|
|
- transformer.queueShapes = ref([])
|
|
|
+ transformer.queueShapes = ref([]);
|
|
|
return transformer;
|
|
|
}, Symbol("transformer"));
|
|
|
|
|
|
export const usePointerIsTransformerInner = () => {
|
|
|
- const transformer = useTransformer()
|
|
|
- const stage = useStage()
|
|
|
+ const transformer = useTransformer();
|
|
|
+ const stage = useStage();
|
|
|
return () => {
|
|
|
- const $stage = stage.value!.getStage()
|
|
|
- const tfRect = transformer.getClientRect()
|
|
|
- tfRect.x -= transformRectPadding
|
|
|
- tfRect.y -= transformRectPadding
|
|
|
- tfRect.width += transformRectPadding
|
|
|
- tfRect.height += transformRectPadding
|
|
|
- const pointRect = { ...$stage.pointerPos!, width: 1, height: 1 }
|
|
|
-
|
|
|
+ const $stage = stage.value!.getStage();
|
|
|
+ const tfRect = transformer.getClientRect();
|
|
|
+ const padding = transformer.padding();
|
|
|
+ tfRect.x -= padding;
|
|
|
+ tfRect.y -= padding;
|
|
|
+ tfRect.width += padding;
|
|
|
+ tfRect.height += padding;
|
|
|
+ const pointRect = { ...$stage.pointerPos!, width: 1, height: 1 };
|
|
|
+
|
|
|
return Util.haveIntersection(tfRect, pointRect);
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+export type TransformerVectorType =
|
|
|
+ | "middle-left"
|
|
|
+ | "middle-right"
|
|
|
+ | "top-center"
|
|
|
+ | "bottom-center"
|
|
|
+ | "top-right"
|
|
|
+ | "top-left"
|
|
|
+ | "bottom-right"
|
|
|
+ | "bottom-left"
|
|
|
+ | "rotater";
|
|
|
+
|
|
|
+export const useGetTransformerVectors = () => {
|
|
|
+ const viewerInvertTransform = useViewerInvertTransform();
|
|
|
+ const transformer = useTransformer();
|
|
|
|
|
|
+ return (type: TransformerVectorType): Pos | null => {
|
|
|
+ if (!transformer.nodes().length) return null;
|
|
|
+ const merTransform = viewerInvertTransform.value
|
|
|
+ .copy()
|
|
|
+ .multiply(transformer.getTransform());
|
|
|
+
|
|
|
+ const getVector = (operateType: TransformerVectorType): Pos => {
|
|
|
+ if (operateType === "rotater") {
|
|
|
+ return vector(getVector("bottom-left"))
|
|
|
+ .add(getVector("bottom-right"))
|
|
|
+ .add(getVector("top-left"))
|
|
|
+ .add(getVector("top-right"))
|
|
|
+ .divideScalar(4);
|
|
|
+ } else {
|
|
|
+ const centerNode = transformer.findOne(`.${operateType}`)!;
|
|
|
+ return {
|
|
|
+ x: centerNode.x(),
|
|
|
+ y: centerNode.y(),
|
|
|
+ };
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return merTransform.point(getVector(type));
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+export const useGetTransformerOrigin = () => {
|
|
|
+ const transformer = useTransformer();
|
|
|
+ const getTransformerVectors = useGetTransformerVectors();
|
|
|
+ const originTypeMap = {
|
|
|
+ "middle-left": "middle-right",
|
|
|
+ "middle-right": "middle-left",
|
|
|
+ "top-center": "bottom-center",
|
|
|
+ "bottom-center": "top-center",
|
|
|
+ "top-right": "bottom-left",
|
|
|
+ "top-left": "bottom-right",
|
|
|
+ "bottom-right": "top-left",
|
|
|
+ "bottom-left": "top-right",
|
|
|
+ 'rotater': "rotater",
|
|
|
+ } as const;
|
|
|
+
|
|
|
+ return (): Pos | null => {
|
|
|
+ if (!transformer.nodes().length) return null;
|
|
|
+ const operateType = transformer.getActiveAnchor() as TransformerVectorType;
|
|
|
+ if (!operateType || !originTypeMap[operateType]) return null;
|
|
|
+ return getTransformerVectors(originTypeMap[operateType]);
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
-export const useShapeDrag = (
|
|
|
- shape: Ref<DC<EntityShape> | undefined>) => {
|
|
|
- const offset = ref<Pos>()
|
|
|
+export const useShapeDrag = (shape: Ref<DC<EntityShape> | undefined>) => {
|
|
|
+ const offset = ref<Pos>();
|
|
|
const mode = useMode();
|
|
|
const conversion = useConversionPosition(true);
|
|
|
- const transformIngShapes = useTransformIngShapes()
|
|
|
+ const transformIngShapes = useTransformIngShapes();
|
|
|
|
|
|
const init = (shape: EntityShape) => {
|
|
|
const dom = shape.getStage()!.container();
|
|
@@ -64,47 +133,47 @@ export const useShapeDrag = (
|
|
|
let start: Pos | undefined;
|
|
|
const enter = (position: Pos) => {
|
|
|
if (!start) {
|
|
|
- start = position
|
|
|
+ start = position;
|
|
|
mode.push(Mode.update);
|
|
|
- transformIngShapes.value.push(shape)
|
|
|
+ transformIngShapes.value.push(shape);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
const leave = () => {
|
|
|
if (start) {
|
|
|
- offset.value = void 0
|
|
|
+ offset.value = void 0;
|
|
|
mode.pop();
|
|
|
start = void 0;
|
|
|
- const ndx = transformIngShapes.value.indexOf(shape)
|
|
|
- ~ndx && transformIngShapes.value.splice(ndx, 1)
|
|
|
+ const ndx = transformIngShapes.value.indexOf(shape);
|
|
|
+ ~ndx && transformIngShapes.value.splice(ndx, 1);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
shape.draggable(true);
|
|
|
shape.dragBoundFunc((_, ev) => {
|
|
|
if (!start) {
|
|
|
- enter(ev)
|
|
|
+ enter(ev);
|
|
|
} else {
|
|
|
const end = conversion(getOffset(ev, dom));
|
|
|
offset.value = {
|
|
|
x: end.x - start.x,
|
|
|
- y: end.y - start.y
|
|
|
- }
|
|
|
+ y: end.y - start.y,
|
|
|
+ };
|
|
|
}
|
|
|
- return shape.absolutePosition()
|
|
|
+ return shape.absolutePosition();
|
|
|
});
|
|
|
|
|
|
shape.on("pointerdown.mouse-drag", (ev) => {
|
|
|
- enter(conversion(getOffset(ev.evt)))
|
|
|
+ enter(conversion(getOffset(ev.evt)));
|
|
|
});
|
|
|
|
|
|
return mergeFuns([
|
|
|
() => {
|
|
|
shape.draggable(false);
|
|
|
shape.off("pointerdown.mouse-status");
|
|
|
- start && leave()
|
|
|
+ start && leave();
|
|
|
},
|
|
|
listener(document.documentElement, "pointerup", () => {
|
|
|
- start && leave()
|
|
|
+ start && leave();
|
|
|
}),
|
|
|
]);
|
|
|
};
|
|
@@ -118,219 +187,248 @@ export const useShapeDrag = (
|
|
|
return offset;
|
|
|
};
|
|
|
|
|
|
-type Rep<T> = { tempShape: T, update: () => void, destory: () => void }
|
|
|
-const emptyFn = () => {}
|
|
|
+type Rep<T> = { tempShape: T; update: () => void; destory: () => void };
|
|
|
+const emptyFn = () => {};
|
|
|
export const useShapeTransformer = <T extends EntityShape>(
|
|
|
- shape: Ref<DC<T> | undefined>,
|
|
|
+ shape: Ref<DC<T> | undefined>,
|
|
|
transformerConfig: TransformerConfig = {},
|
|
|
- replaceShape?: (transformer: TransformerExtends, shape: T) => Rep<T>
|
|
|
+ replaceShape?: (transformer: TransformerExtends, shape: T) => Rep<T>,
|
|
|
+ handlerTransform?: (transform: Transform) => Transform
|
|
|
) => {
|
|
|
- const offset = useShapeDrag(shape)
|
|
|
- const transform = ref<Transform>()
|
|
|
+ const offset = useShapeDrag(shape);
|
|
|
+ const transform = ref<Transform>();
|
|
|
const status = useMouseShapeStatus(shape);
|
|
|
const mode = useMode();
|
|
|
const transformer = useTransformer();
|
|
|
- const transformIngShapes = useTransformIngShapes()
|
|
|
-
|
|
|
- const init = ($shape: T) => mergeFuns(
|
|
|
- watch(
|
|
|
- () => status.value.hover,
|
|
|
- (active, _, onCleanup) => {
|
|
|
- const parent = $shape.parent;
|
|
|
- if (!(active && parent)) return;
|
|
|
- const oldConfig: TransformerConfig = {}
|
|
|
-
|
|
|
- for (const key in transformerConfig) {
|
|
|
- oldConfig[key] = (transformer as any)[key]();
|
|
|
- (transformer as any)[key](transformerConfig[key]);
|
|
|
- }
|
|
|
-
|
|
|
- let rep: Rep<T>
|
|
|
- if (replaceShape) {
|
|
|
- rep = replaceShape(transformer, $shape)
|
|
|
- } else {
|
|
|
- rep = {
|
|
|
- tempShape: $shape,
|
|
|
- destory: emptyFn,
|
|
|
- update: emptyFn
|
|
|
+ const transformIngShapes = useTransformIngShapes();
|
|
|
+
|
|
|
+ const init = ($shape: T) =>
|
|
|
+ mergeFuns(
|
|
|
+ watch(
|
|
|
+ () => status.value.hover,
|
|
|
+ (active, _, onCleanup) => {
|
|
|
+ const parent = $shape.parent;
|
|
|
+ if (!(active && parent)) return;
|
|
|
+ const oldConfig: TransformerConfig = {};
|
|
|
+
|
|
|
+ for (const key in transformerConfig) {
|
|
|
+ oldConfig[key] = (transformer as any)[key]();
|
|
|
+ (transformer as any)[key](transformerConfig[key]);
|
|
|
}
|
|
|
- transformer.nodes([$shape])
|
|
|
- transformer.queueShapes.value = [$shape]
|
|
|
- }
|
|
|
- parent.add(transformer);
|
|
|
-
|
|
|
- const updateTransform = () => {
|
|
|
- transform.value = rep.tempShape.getTransform().copy()
|
|
|
- }
|
|
|
|
|
|
- const downHandler = () => {
|
|
|
- isEnter && mode.pop()
|
|
|
- isEnter = true
|
|
|
- rep.update()
|
|
|
- mode.push(Mode.update);
|
|
|
- transformIngShapes.value.push($shape)
|
|
|
- }
|
|
|
-
|
|
|
- let isEnter = false
|
|
|
- transformer.on("pointerdown.shapemer", downHandler);
|
|
|
- transformer.on("transform.shapemer", updateTransform);
|
|
|
- const stop = listener($shape.getStage()!.container(), "pointerup", () => {
|
|
|
- if (isEnter) {
|
|
|
- mode.pop()
|
|
|
- transform.value = void 0
|
|
|
- isEnter = false
|
|
|
- const ndx = transformIngShapes.value.indexOf($shape)
|
|
|
- ~ndx && transformIngShapes.value.splice(ndx, 1)
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- // 拖拽时要更新矩阵
|
|
|
- let prevMoveTf: Transform | null = null
|
|
|
- const stopDragWatch = watch(offset, (translate, oldTranslate) => {
|
|
|
- if (translate) {
|
|
|
- if (!oldTranslate) {
|
|
|
- rep.update()
|
|
|
- }
|
|
|
- const moveTf = new Transform().translate(translate.x, translate.y)
|
|
|
- const finalTf = moveTf.copy()
|
|
|
- prevMoveTf && finalTf.multiply(prevMoveTf.invert())
|
|
|
- finalTf.multiply(rep.tempShape.getTransform())
|
|
|
- prevMoveTf = moveTf
|
|
|
-
|
|
|
- setShapeTransform(rep.tempShape, finalTf);
|
|
|
- updateTransform()
|
|
|
+ let rep: Rep<T>;
|
|
|
+ if (replaceShape) {
|
|
|
+ rep = replaceShape(transformer, $shape);
|
|
|
} else {
|
|
|
- prevMoveTf = null
|
|
|
- transform.value = void 0
|
|
|
+ rep = {
|
|
|
+ tempShape: $shape,
|
|
|
+ destory: emptyFn,
|
|
|
+ update: emptyFn,
|
|
|
+ };
|
|
|
+ transformer.nodes([$shape]);
|
|
|
+ transformer.queueShapes.value = [$shape];
|
|
|
}
|
|
|
- }, { immediate: true })
|
|
|
+ parent.add(transformer);
|
|
|
|
|
|
- onCleanup(() => {
|
|
|
- for (const key in oldConfig) {
|
|
|
- ;(transformer as any)[key](oldConfig[key]);
|
|
|
- }
|
|
|
- stop()
|
|
|
- stopDragWatch()
|
|
|
- parent.add($shape);
|
|
|
- // TODO: 有可能transformer已经转移
|
|
|
- if (transformer.queueShapes.value.includes($shape)) {
|
|
|
- transformer.nodes([]);
|
|
|
- transformer.queueShapes.value = []
|
|
|
- }
|
|
|
- transform.value = void 0;
|
|
|
- rep.destory()
|
|
|
- if (isEnter) {
|
|
|
- mode.pop()
|
|
|
- const ndx = transformIngShapes.value.indexOf($shape)
|
|
|
- ~ndx && transformIngShapes.value.splice(ndx, 1)
|
|
|
- }
|
|
|
- transformer.off("pointerdown.shapemer", downHandler);
|
|
|
- transformer.off("transform.shapemer", updateTransform);
|
|
|
- });
|
|
|
- },
|
|
|
- { immediate: true }
|
|
|
- )
|
|
|
- )
|
|
|
+ const updateTransform = () => {
|
|
|
+ let appleTransform = rep.tempShape.getTransform().copy();
|
|
|
+ if (handlerTransform) {
|
|
|
+ appleTransform = handlerTransform(appleTransform);
|
|
|
+ setShapeTransform(rep.tempShape, appleTransform);
|
|
|
+ }
|
|
|
+ transform.value = appleTransform;
|
|
|
+ };
|
|
|
+
|
|
|
+ const downHandler = () => {
|
|
|
+ isEnter && mode.pop();
|
|
|
+ isEnter = true;
|
|
|
+ rep.update();
|
|
|
+ mode.push(Mode.update);
|
|
|
+ transformIngShapes.value.push($shape);
|
|
|
+ };
|
|
|
+
|
|
|
+ let isEnter = false;
|
|
|
+ transformer.on("pointerdown.shapemer", downHandler);
|
|
|
+ transformer.on("transform.shapemer", updateTransform);
|
|
|
+ const stop = listener(
|
|
|
+ $shape.getStage()!.container(),
|
|
|
+ "pointerup",
|
|
|
+ () => {
|
|
|
+ if (isEnter) {
|
|
|
+ mode.pop();
|
|
|
+ transform.value = void 0;
|
|
|
+ isEnter = false;
|
|
|
+ const ndx = transformIngShapes.value.indexOf($shape);
|
|
|
+ ~ndx && transformIngShapes.value.splice(ndx, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ // 拖拽时要更新矩阵
|
|
|
+ let prevMoveTf: Transform | null = null;
|
|
|
+ const stopDragWatch = watch(
|
|
|
+ offset,
|
|
|
+ (translate, oldTranslate) => {
|
|
|
+ if (translate) {
|
|
|
+ if (!oldTranslate) {
|
|
|
+ rep.update();
|
|
|
+ }
|
|
|
+ const moveTf = new Transform().translate(
|
|
|
+ translate.x,
|
|
|
+ translate.y
|
|
|
+ );
|
|
|
+ const finalTf = moveTf.copy();
|
|
|
+ prevMoveTf && finalTf.multiply(prevMoveTf.invert());
|
|
|
+ finalTf.multiply(rep.tempShape.getTransform());
|
|
|
+ prevMoveTf = moveTf;
|
|
|
+
|
|
|
+ setShapeTransform(rep.tempShape, finalTf);
|
|
|
+ transformer.fire("transform");
|
|
|
+ // updateTransform()
|
|
|
+ } else {
|
|
|
+ prevMoveTf = null;
|
|
|
+ transform.value = void 0;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+ );
|
|
|
+
|
|
|
+ onCleanup(() => {
|
|
|
+ for (const key in oldConfig) {
|
|
|
+ (transformer as any)[key](oldConfig[key]);
|
|
|
+ }
|
|
|
+ stop();
|
|
|
+ stopDragWatch();
|
|
|
+ // parent.add($shape);
|
|
|
+ // TODO: 有可能transformer已经转移
|
|
|
+ if (transformer.queueShapes.value.includes($shape)) {
|
|
|
+ transformer.nodes([]);
|
|
|
+ transformer.queueShapes.value = [];
|
|
|
+ // transformer.remove();
|
|
|
+ }
|
|
|
+ transform.value = void 0;
|
|
|
+ rep.destory();
|
|
|
+ if (isEnter) {
|
|
|
+ mode.pop();
|
|
|
+ const ndx = transformIngShapes.value.indexOf($shape);
|
|
|
+ ~ndx && transformIngShapes.value.splice(ndx, 1);
|
|
|
+ }
|
|
|
+ transformer.off("pointerdown.shapemer", downHandler);
|
|
|
+ transformer.off("transform.shapemer", updateTransform);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+ )
|
|
|
+ );
|
|
|
watch(shape, (shape, _, onCleanup) => {
|
|
|
if (shape) {
|
|
|
- onCleanup(init(shape.getStage()));
|
|
|
+ const stop = init(shape.getStage());
|
|
|
+ onCleanup(stop);
|
|
|
+ } else {
|
|
|
+ onCleanup(() => {});
|
|
|
}
|
|
|
});
|
|
|
return transform;
|
|
|
};
|
|
|
|
|
|
-
|
|
|
export const genTransformerRepShape = <T extends Shape>(
|
|
|
- shape: T,
|
|
|
+ shape: T,
|
|
|
transformer: TransformerExtends,
|
|
|
getAttitudeMat: () => number[],
|
|
|
resumeData: (repShape: T, inverAttitude: Transform) => void
|
|
|
) => {
|
|
|
- const repShape = shape.clone({
|
|
|
- fill: 'rgb(0, 255, 0)',
|
|
|
- visible: false,
|
|
|
- strokeWidth: 0
|
|
|
- })
|
|
|
+ const repShape = shape.clone({
|
|
|
+ fill: "rgb(0, 255, 0)",
|
|
|
+ visible: false,
|
|
|
+ strokeWidth: 0,
|
|
|
+ });
|
|
|
|
|
|
const update = () => {
|
|
|
const attitude = new Transform(getAttitudeMat());
|
|
|
const inverAttitude = attitude.copy().invert();
|
|
|
- setShapeTransform(repShape, attitude)
|
|
|
- resumeData(repShape, inverAttitude)
|
|
|
- }
|
|
|
-
|
|
|
+ setShapeTransform(repShape, attitude);
|
|
|
+ resumeData(repShape, inverAttitude);
|
|
|
+ };
|
|
|
|
|
|
if (import.meta.env.DEV) {
|
|
|
- repShape.visible(true)
|
|
|
- shape.opacity(0.9)
|
|
|
- repShape.opacity(0.1)
|
|
|
+ repShape.visible(true);
|
|
|
+ shape.opacity(0.9);
|
|
|
+ repShape.opacity(0.1);
|
|
|
}
|
|
|
|
|
|
- update()
|
|
|
- shape.parent!.add(repShape)
|
|
|
- repShape.zIndex(shape.getZIndex() - 1)
|
|
|
+ update();
|
|
|
+ shape.parent!.add(repShape);
|
|
|
+ repShape.zIndex(shape.getZIndex());
|
|
|
transformer.nodes([repShape]);
|
|
|
- transformer.queueShapes.value = [shape]
|
|
|
+ transformer.queueShapes.value = [shape];
|
|
|
|
|
|
return {
|
|
|
tempShape: repShape,
|
|
|
update,
|
|
|
destory: () => {
|
|
|
- repShape.remove()
|
|
|
- shape.opacity(1)
|
|
|
- }
|
|
|
+ repShape.remove();
|
|
|
+ shape.opacity(1);
|
|
|
+ },
|
|
|
};
|
|
|
-}
|
|
|
-
|
|
|
+};
|
|
|
|
|
|
export type LineTransformerData = {
|
|
|
- points: Pos[],
|
|
|
- attitude: number[]
|
|
|
-}
|
|
|
-export const useLineTransformer = (
|
|
|
+ points: Pos[];
|
|
|
+ attitude: number[];
|
|
|
+};
|
|
|
+export const useLineTransformer = <T extends LineTransformerData>(
|
|
|
shape: Ref<DC<Line> | undefined>,
|
|
|
- init: () => LineTransformerData,
|
|
|
- callback: (data: LineTransformerData) => void,
|
|
|
+ data: Ref<T>,
|
|
|
+ callback: (data: T) => void
|
|
|
) => {
|
|
|
- const data = useAutomaticData(() => init())
|
|
|
- let tempShape: Line
|
|
|
- let inverAttitude: Transform
|
|
|
- let stableVs = data.value.points
|
|
|
- let tempVs = data.value.points
|
|
|
-
|
|
|
- const transform = useShapeTransformer(shape, undefined, (transformer, $shape) => {
|
|
|
- const result = genTransformerRepShape(
|
|
|
- $shape,
|
|
|
- transformer,
|
|
|
- () => data.value.attitude, (repShape, inverMat) => {
|
|
|
- const initVs = stableVs.map(v => inverMat.point(v))
|
|
|
- repShape.points(flatPositions(initVs) )
|
|
|
- repShape.closed(true)
|
|
|
- inverAttitude = inverMat
|
|
|
- }
|
|
|
- )
|
|
|
- tempShape = result.tempShape
|
|
|
- return result
|
|
|
- })
|
|
|
-
|
|
|
- watch(() => shape.value?.getNode(), $shape => {
|
|
|
- if ($shape) {
|
|
|
- $shape.points(flatPositions(tempVs))
|
|
|
+ let tempShape: Line;
|
|
|
+ let inverAttitude: Transform;
|
|
|
+ let stableVs = data.value.points;
|
|
|
+ let tempVs = data.value.points;
|
|
|
+ let operateShape: Line;
|
|
|
+
|
|
|
+ const transformer = useTransformer();
|
|
|
+ const transform = useShapeTransformer(
|
|
|
+ shape,
|
|
|
+ undefined,
|
|
|
+ (transformer, $shape) => {
|
|
|
+ const result = genTransformerRepShape(
|
|
|
+ $shape,
|
|
|
+ transformer,
|
|
|
+ () => data.value.attitude,
|
|
|
+ (repShape, inverMat) => {
|
|
|
+ const initVs = stableVs.map((v) => inverMat.point(v));
|
|
|
+ repShape.points(flatPositions(initVs));
|
|
|
+ repShape.closed(true);
|
|
|
+ inverAttitude = inverMat;
|
|
|
+ operateShape = repShape;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ tempShape = result.tempShape;
|
|
|
+ return result;
|
|
|
}
|
|
|
- })
|
|
|
+ );
|
|
|
|
|
|
+ const [snapToPoints, clearSnap] = useSnapToPoints((data as any).value.id);
|
|
|
watch(transform, (current, prev) => {
|
|
|
if (current) {
|
|
|
// 顶点更新
|
|
|
- const $shape = shape.value!.getNode()
|
|
|
- const transfrom = current.copy().multiply(inverAttitude)
|
|
|
- tempVs = stableVs.map(v => transfrom.point(v))
|
|
|
- $shape.points(flatPositions(tempVs))
|
|
|
+ const transfrom = current.copy().multiply(inverAttitude);
|
|
|
+ tempVs = stableVs.map((v) => transfrom.point(v));
|
|
|
+ const snapTransform = snapToPoints({
|
|
|
+ ...data.value,
|
|
|
+ points: tempVs,
|
|
|
+ } as any);
|
|
|
+ if (snapTransform) {
|
|
|
+ tempVs = tempVs.map((v) => snapTransform.point(v));
|
|
|
+ }
|
|
|
+ data.value.points = tempVs;
|
|
|
} else if (prev && tempShape) {
|
|
|
data.value.attitude = tempShape.getTransform().m;
|
|
|
- data.value.points = stableVs = tempVs
|
|
|
- callback(data.value)
|
|
|
+ data.value.points = stableVs = tempVs;
|
|
|
+ callback(data.value);
|
|
|
+ clearSnap();
|
|
|
}
|
|
|
- })
|
|
|
- return [transform, data] as const
|
|
|
-}
|
|
|
+ });
|
|
|
+ return transform;
|
|
|
+};
|