123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <template>
- <v-line
- ref="line"
- :config="{
- id: id,
- strokeWidth: data.strokeWidth,
- opacity: opacity || 0,
- stroke: data.stroke,
- points: flatPositions(points),
- hitStrokeWidth: data.strokeWidth,
- }"
- />
- <v-circle
- v-if="!disablePoint"
- :config="{ ...pointStyle, ...center, opacity: isHover || isPointHover ? 1 : 0 }"
- ref="point"
- />
- </template>
- <script lang="ts" setup>
- import { copy, flatPositions } from "@/utils/shared";
- import { computed, ref, watch } from "vue";
- import { DC } from "@/deconstruction";
- import { Line } from "konva/lib/shapes/Line";
- import { useShapeDrag } from "@/core/hook/use-transformer";
- import { useShapeIsHover, useShapeClick } from "@/core/hook/use-mouse-status";
- import { useCursor } from "@/core/hook/use-global-vars";
- import { lineCenter, Pos } from "@/utils/math";
- import { useCustomSnapInfos, useGlobalSnapInfos, useSnap } from "@/core/hook/use-snap";
- import { ComponentSnapInfo } from "..";
- import { generateSnapInfos } from "../util";
- import { getMouseColors } from "@/utils/colors";
- import { themeColor } from "@/constant";
- import { Circle } from "konva/lib/shapes/Circle";
- import { SLineData } from "../sequent-line";
- import { useViewer } from "@/core/hook/use-viewer";
- type LData = Required<Pick<SLineData, "strokeWidth" | "stroke">>;
- const props = defineProps<{
- data: LData;
- points: Pos[];
- id: string;
- ndx: number;
- closed?: boolean;
- disablePoint?: boolean;
- opacity?: number;
- }>();
- const emit = defineEmits<{
- (e: "update:line", data: Pos[]): void;
- (e: "dragend"): void;
- (e: "dragstart"): void;
- (e: "addPoint", pos: Pos): void;
- }>();
- const line = ref<DC<Line>>();
- const offset = useShapeDrag(line);
- const viewer = useViewer();
- const [isHover] = useShapeIsHover(line);
- const cursor = useCursor();
- watch(isHover, (hover, _, onCleanup) => {
- if (hover) {
- onCleanup(cursor.push("./icons/m_move.png"));
- }
- });
- const points = computed(() => {
- return [props.points[props.ndx], props.points[(props.ndx + 1) % props.points.length]];
- });
- const infos = useCustomSnapInfos();
- const addedInfos = [] as ComponentSnapInfo[];
- const clearInfos = () => {
- addedInfos.forEach(infos.remove);
- };
- const dragStartHandler = () => {
- viewer.disabled.value = true;
- clearInfos();
- const ndx = props.ndx;
- const geos = [
- props.points.slice(Number(ndx === props.points.length - 1), ndx),
- props.points.slice(ndx + 2, props.points.length),
- ];
- if (ndx > 0 && ndx < props.points.length - 2) {
- geos.push([props.points[ndx - 1], props.points[ndx + 2]]);
- }
- geos.forEach((geo) => {
- const snapInfos = generateSnapInfos(geo, true, true, true);
- snapInfos.forEach((item) => {
- infos.add(item);
- addedInfos.push(item);
- });
- });
- };
- const snapInfos = useGlobalSnapInfos();
- const refSnapInfos = computed(() => {
- if (!props.id) {
- return snapInfos.value;
- } else {
- return snapInfos.value.filter((p) => !("id" in p) || p.id !== props.id);
- }
- });
- const snap = useSnap(refSnapInfos);
- let init: Pos[];
- watch(offset, (offset, oldOffsert) => {
- snap.clear();
- if (!oldOffsert) {
- emit("dragstart");
- init = copy(points.value);
- dragStartHandler();
- }
- if (offset) {
- const current = init.map((p) => ({
- x: p.x + offset.x,
- y: p.y + offset.y,
- }));
- const refSnapInfos = generateSnapInfos(current, true, true);
- const transform = snap.move(refSnapInfos);
- emit("update:line", transform ? current.map((p) => transform.point(p)) : current);
- } else {
- clearInfos();
- emit("dragend");
- viewer.disabled.value = false;
- }
- });
- const point = ref<DC<Circle>>();
- const [isPointHover] = useShapeIsHover(point);
- let addCursorPop: () => void;
- watch(isPointHover, (hover, _, onCleanup) => {
- if (hover) {
- let pop: (() => void) | null = cursor.push("./icons/m_add.png");
- addCursorPop = () => {
- pop && pop();
- pop = null;
- };
- onCleanup(addCursorPop);
- }
- });
- useShapeClick(point, () => {
- emit("addPoint", { ...center.value });
- addCursorPop();
- });
- const center = computed(() => lineCenter(points.value));
- const pointStyle = computed(() => {
- const color = getMouseColors(props.data.stroke || themeColor);
- const size = props.data.strokeWidth + 6 || 5;
- return {
- radius: size / 2,
- fill: "#fff",
- strokeWidth: size / 4,
- stroke: color.pub,
- };
- });
- defineExpose({
- get shape() {
- return line.value;
- },
- });
- </script>
|