123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <template>
- <EditLine
- :ref="(d: any) => shape = d?.shape"
- :data="{ ...line, ...style, lineJoin: 'miter' }"
- :opacity="isDrawIng ? 0.5 : 1"
- :points="points"
- :closed="false"
- :id="line.id"
- :disablePoint="!canEdit || mode.include(Mode.readonly)"
- :ndx="0"
- @dragstart="emit('dragLineStart', props.line)"
- @update:line="(ps) => emit('dragLine', props.line, ps)"
- @dragend="emit('dragLineEnd', props.line)"
- @add-point="addPoint"
- />
- <template v-for="polygons in joinsPolygons">
- <v-line v-for="config in polygons" :config="config" />
- </template>
- <SizeLine
- v-if="
- status.active ||
- config.showComponentSize ||
- isDrawIng ||
- dragPointIds?.includes(line.a) ||
- dragPointIds?.includes(line.b)
- "
- :points="points"
- :strokeWidth="style.strokeWidth"
- :stroke="style.stroke"
- />
- <template v-if="(!mode.include(Mode.readonly) && canEdit) || isDrawIng">
- <EditPoint
- v-for="(point, ndx) in points"
- :key="point.id"
- :size="line.strokeWidth"
- :points="points"
- :opacity="0.1"
- :drawIng="ndx === 0 && isDrawIng"
- :ndx="ndx"
- :closed="false"
- :id="line.id"
- :disable="addMode"
- :color="isDrawIng ? themeColor : style.stroke"
- @dragstart="dragstartHandler([point.id])"
- @update:position="(p) => emit('updatePoint', { ...point, ...p })"
- @dragend="dragendHandler"
- @delete="delPoint(point)"
- />
- </template>
- <PropertyUpdate
- :describes="describes"
- :data="line"
- :target="shape"
- :name="shapeName"
- @change="
- () => {
- isStartChange || emit('updateBefore', []);
- emit('updateLine', { ...line });
- emit('update');
- isStartChange = false;
- }
- "
- @delete="delHandler"
- />
- <Operate :target="shape" :menus="menus" />
- </template>
- <script lang="ts" setup>
- import { computed, ref, watchEffect } from "vue";
- import { getMouseStyle, getSnapInfos, LineData, shapeName } from "./index.ts";
- import { flatPositions, onlyId } from "@/utils/shared.ts";
- import EditLine from "../share/edit-line.vue";
- import { getVectorLine, lineCenter, lineLen, lineVector, Pos } from "@/utils/math.ts";
- import { Line } from "konva/lib/shapes/Line";
- import { DC } from "@/deconstruction.js";
- import { useMode } from "@/core/hook/use-status.ts";
- import { Mode } from "@/constant/mode.ts";
- import SizeLine from "../share/size-line.vue";
- import { useConfig } from "@/core/hook/use-config.ts";
- import { ComponentSnapInfo } from "../index.ts";
- import { useCustomSnapInfos } from "@/core/hook/use-snap.ts";
- import { mergeDescribes } from "@/core/html-mount/propertys/index.ts";
- import { PropertyUpdate, Operate } from "../../html-mount/propertys/index.ts";
- import {
- useAnimationMouseStyle,
- useMouseShapeStatus,
- } from "@/core/hook/use-mouse-status.ts";
- import { themeColor } from "@/constant";
- import { Vector2 } from "three";
- import { extendLinesOverlap } from "./attach-view.ts";
- import EditPoint from "../share/edit-point.vue";
- const mode = useMode();
- const props = defineProps<{
- line: LineData["lines"][number];
- addMode?: boolean;
- canEdit?: boolean;
- data: LineData;
- dragPointIds?: string[];
- }>();
- const joinsPolygons = extendLinesOverlap(props.data, props.line);
- const emit = defineEmits<{
- (e: "updatePoint", value: LineData["points"][number]): void;
- (e: "addPoint", value: LineData["points"][number]): void;
- (e: "delPoint", value: LineData["points"][number]): void;
- (e: "delLine"): void;
- (e: "updateLine", value: LineData["lines"][number]): void;
- (e: "updateBefore", value: string[]): void;
- (e: "update"): void;
- (e: "dragLineStart", value: LineData["lines"][number]): void;
- (e: "dragLine", line: LineData["lines"][number], move: Pos[]): void;
- (e: "dragLineEnd", value: LineData["lines"][number]): void;
- }>();
- const shape = ref<DC<Line>>();
- const points = computed(() => [
- props.data.points.find((p) => p.id === props.line.a)!,
- props.data.points.find((p) => p.id === props.line.b)!,
- ]);
- const lineData = computed(() => props.line);
- const describes = mergeDescribes(lineData, {}, ["stroke", "strokeWidth"]);
- const d = describes as any;
- d.strokeWidth.props = {
- ...d.strokeWidth.props,
- proportion: true,
- };
- d.strokeWidth.label = "粗细";
- d.stroke.label = "颜色";
- let isStartChange = false;
- let setLineVector: Vector2;
- describes.length = {
- type: "inputNum",
- label: "线段长度",
- "layout-type": "row",
- get value() {
- return lineLen(points.value[0], points.value[1]);
- },
- set value(val) {
- if (!isStartChange) {
- emit("updateBefore", [props.line.a, props.line.b]);
- setLineVector = lineVector(points.value);
- }
- isStartChange = true;
- const aCount = props.data.lines.filter(
- (line) => line.a === points.value[0].id || line.b === points.value[0].id
- ).length;
- const bCount = props.data.lines.filter(
- (line) => line.a === points.value[1].id || line.b === points.value[1].id
- ).length;
- if (aCount === bCount || (aCount > 1 && bCount > 1)) {
- // 两端伸展
- const center = lineCenter(points.value);
- const l1 = getVectorLine(setLineVector.clone().multiplyScalar(-1), center, val / 2);
- const l2 = getVectorLine(setLineVector, center, val / 2);
- emit("updatePoint", { ...points.value[0], ...l1[1] });
- emit("updatePoint", { ...points.value[1], ...l2[1] });
- } else {
- // 单端伸展
- const changeNdx = aCount > 1 ? 1 : 0;
- const start = points.value[aCount > 1 ? 0 : 1];
- const lineVec =
- aCount > 1 ? setLineVector : setLineVector.clone().multiplyScalar(-1);
- const line = getVectorLine(lineVec, start, val);
- emit("updatePoint", { ...points.value[changeNdx], ...line[1] });
- }
- },
- props: { proportion: true },
- };
- const delHandler = () => {
- emit("updateBefore", [props.line.a, props.line.b]);
- emit("delLine");
- emit("update");
- };
- const menus = [
- {
- label: "删除",
- handler: delHandler,
- },
- ];
- const status = useMouseShapeStatus(shape);
- const [mstyle] = useAnimationMouseStyle({
- shape,
- getMouseStyle,
- data: lineData as any,
- });
- const isDrawIng = computed(
- () =>
- props.addMode && props.data.lines.indexOf(props.line) === props.data.lines.length - 1
- );
- const style = computed(() =>
- isDrawIng.value ? { ...mstyle.value, stroke: themeColor } : mstyle.value
- );
- const addPoint = (pos: Pos) => {
- emit("updateBefore", []);
- emit("addPoint", { ...points.value[0], ...pos, id: onlyId() });
- emit("update");
- };
- const config = useConfig();
- const delPoint = (point: LineData["points"][number]) => {
- emit("updateBefore", []);
- emit("delPoint", point);
- emit("update");
- };
- const infos = useCustomSnapInfos();
- let snapInfos: ComponentSnapInfo[];
- const dragstartHandler = (eIds: string[]) => {
- emit("updateBefore", eIds);
- snapInfos = getSnapInfos({
- ...props.data,
- lines: props.data.lines.filter(
- (item) => !(eIds.includes(item.a) || eIds.includes(item.b))
- ),
- points: props.data.points.filter((item) => !eIds.includes(item.id)),
- });
- snapInfos.forEach((item) => {
- infos.add(item);
- });
- };
- const dragendHandler = () => {
- emit("update");
- snapInfos.forEach((item) => infos.remove(item));
- };
- // const padstart = computed(() => {
- // props.line.
- // })
- </script>
|