123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <template>
- <TempIcon :data="tData" :ref="(e: any) => shape = e?.shape" />
- <PropertyUpdate
- :describes="describes"
- :data="data"
- :target="shape"
- @delete="emit('delShape')"
- @change="emit('updateShape', { ...data })"
- />
- <Operate :target="shape" :menus="operateMenus" />
- </template>
- <script lang="ts" setup>
- import TempIcon from "./temp-icon.vue";
- import {
- LineIconData,
- getMouseStyle,
- defaultStyle,
- matResponse,
- getLineIconMat,
- getSnapLine,
- getLineIconEndpoints,
- isRangInner,
- } from "./index.ts";
- import { useComponentStatus } from "@/core/hook/use-component.ts";
- import { PropertyUpdate, Operate } from "../../html-mount/propertys/index.ts";
- import { Transform } from "konva/lib/Util";
- import {
- useCustomTransformer,
- useGetTransformerOperType,
- } from "@/core/hook/use-transformer.ts";
- import { Group } from "konva/lib/Group";
- import { Rect } from "konva/lib/shapes/Rect";
- import { setShapeTransform } from "@/utils/shape.ts";
- import { useStore } from "@/core/store/index.ts";
- import { usePointerPos } from "@/core/hook/use-global-vars.ts";
- import { useViewerInvertTransform } from "@/core/hook/use-viewer.ts";
- import { computed, nextTick, watch } from "vue";
- import { useHistory } from "@/core/hook/use-history.ts";
- import {
- eqPoint,
- line2IncludedAngle,
- lineInner,
- lineLen,
- lineVector,
- Pos,
- zeroEq,
- } from "@/utils/math.ts";
- import { copy } from "@/utils/shared.ts";
- import { useTestPoints } from "@/core/hook/use-debugger.ts";
- const props = defineProps<{ data: LineIconData }>();
- const emit = defineEmits<{
- (e: "updateShape", value: LineIconData): void;
- (e: "addShape", value: LineIconData): void;
- (e: "delShape"): void;
- }>();
- const store = useStore();
- const getOperType = useGetTransformerOperType();
- const viewMat = useViewerInvertTransform();
- const pos = usePointerPos();
- const testPoints = useTestPoints();
- const { shape, tData, data, operateMenus, describes } = useComponentStatus({
- emit,
- props,
- getMouseStyle,
- transformType: "custom",
- selfData: true,
- customTransform(callback, shape, data) {
- let prevInvMat: Transform;
- let posOffset: Pos | null = null;
- return useCustomTransformer(shape, data, {
- getRepShape() {
- const group = new Group();
- const rect = new Rect();
- group.add(rect);
- const update = () => {
- const mat = getLineIconMat(getSnapLine(store, data.value)!, data.value);
- const width = Math.abs(data.value.endLen - data.value.startLen);
- const height = data.value.height;
- prevInvMat = mat;
- rect.width(width);
- rect.height(height);
- rect.offset({ x: width / 2, y: height / 2 });
- setShapeTransform(group, mat);
- };
- update();
- return { shape: group, update };
- },
- handler(data, mat) {
- if (pos.value && !getOperType()) {
- // if (!posOffset) {
- // const real = viewMat.value.point(pos.value);
- // const prevDec = prevInvMat.decompose();
- // posOffset = {
- // x: real.x - prevDec.x,
- // y: real.y - prevDec.y,
- // };
- // testPoints.value = [
- // {
- // x: real.x - posOffset.x,
- // y: real.y - posOffset.y,
- // },
- // ];
- // }
- const rpos = viewMat.value.point({
- x: pos.value.x,
- y: pos.value.y,
- });
- const m = mat.m;
- m[4] = rpos.x;
- m[5] = rpos.y;
- // m[4] = rpos.x - posOffset.x;
- // m[5] = rpos.y - posOffset.y;
- mat = new Transform(m);
- }
- matResponse({
- data,
- mat: mat,
- operType: getOperType(),
- store,
- });
- return true;
- },
- callback() {
- posOffset = null;
- callback();
- },
- openSnap: false,
- transformerConfig: {
- flipEnabled: true,
- rotateEnabled: false,
- enabledAnchors: ["middle-left", "middle-right"],
- boundBoxFunc: (oldBox, newBox) => {
- if (newBox.width < 5) {
- return oldBox;
- } else {
- return newBox;
- }
- },
- },
- });
- },
- defaultStyle,
- copyHandler(_, data) {
- const snapLine = getSnapLine(store, data)!;
- const line = getLineIconEndpoints(getSnapLine(store, data)!, data);
- const vector = lineVector(line);
- const move = vector.multiplyScalar(lineLen(line[0], line[1]));
- const mat = new Transform()
- .translate(move.x, move.y)
- .multiply(getLineIconMat(snapLine, data));
- return matResponse({ data, mat, store });
- },
- propertys: ["name", "fill", "stroke", "strokeWidth"],
- });
- const lineRaw = computed(() => {
- const line = store.getTypeItems("line")[0];
- return line.lines.find((item) => item.id === props.data.lineId);
- });
- const line = computed(() => getSnapLine(store, props.data));
- const history = useHistory();
- watch(
- () => ({
- line: line.value && (copy(line.value) as Pos[]),
- width: lineRaw.value?.strokeWidth,
- }),
- (newv, oldv) => {
- const line = newv.line;
- const oldLine = oldv?.line;
- history.preventTrack(() => {
- if (!line) {
- console.error("找不到line", props.data);
- return emit("delShape");
- }
- if (!oldLine) return;
- const eq0 = eqPoint(oldLine[0], line[0]);
- const eq1 = eqPoint(oldLine[1], line[1]);
- if (!eq0 || !eq1) {
- if (eq0 === eq1) {
- let newLen = lineLen(line[0], line[1]);
- if (zeroEq(newLen - lineLen(oldLine[0], oldLine[1]))) {
- shape.value?.getNode().fire("bound-change");
- return;
- }
- if (!isRangInner(line, data.value)) {
- emit("delShape");
- return;
- }
- } else {
- // 联动
- const startNdx = eq0 ? 0 : 1;
- const endNdx = eq0 ? 1 : 0;
- const rotate = line2IncludedAngle(
- [oldLine[startNdx], oldLine[endNdx]],
- [line[startNdx], line[endNdx]]
- );
- const mat = new Transform()
- .translate(line[startNdx].x, line[startNdx].y)
- .rotate(rotate)
- .translate(-line[startNdx].x, -line[startNdx].y);
- const endPoints = getLineIconEndpoints(oldLine, data.value).map((p) =>
- mat.point(p)
- );
- if (lineInner(line, endPoints[0]) && lineInner(line, endPoints[1])) {
- emit("updateShape", {
- ...data.value,
- startLen: lineLen(line[0], endPoints[0]),
- endLen: lineLen(line[0], endPoints[1]),
- });
- } else {
- emit("delShape");
- return;
- }
- }
- } else if (newv.width !== oldv.width && newv.width && props.data.type === "full") {
- emit("updateShape", { ...data.value, height: newv.width });
- }
- nextTick(() => {
- shape.value?.getNode().fire("bound-change");
- });
- });
- },
- { immediate: true, flush: "post" }
- );
- operateMenus.splice(0, 2);
- operateMenus.splice(1, 2);
- // if (props.data.type === "align-bottom" || props.data.type === "align-bottom-fix") {
- operateMenus.splice(
- operateMenus.length - 2,
- 0,
- // {
- // label: "内外翻转",
- // handler: () => {
- // emit("updateShape", {
- // ...data.value,
- // openSide: data.value.openSide === "LEFT" ? "RIGHT" : "LEFT",
- // });
- // },
- // },
- {
- label: "翻转",
- handler: () => {
- emit("updateShape", {
- ...data.value,
- openSide: data.value.openSide === "LEFT" ? "RIGHT" : "LEFT",
- startLen: data.value.endLen,
- endLen: data.value.startLen,
- });
- },
- }
- );
- // }
- </script>
|