| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- <template>
- <v-circle
- :config="{ ...style, ...position, hitStrokeWidth: style.strokeWidth }"
- ref="circle"
- />
- <Operate
- :target="circle"
- :menus="[{ label: '删除', handler: () => emit('delete') }]"
- v-if="!notDelete"
- />
- </template>
- <script lang="ts" setup>
- import { Pos } from "@/utils/math.ts";
- import { themeColor } from "@/constant";
- import { computed, onUnmounted, ref, watch } from "vue";
- import { DC } from "@/deconstruction";
- import { Circle } from "konva/lib/shapes/Circle";
- import { useShapeDrag } from "@/core/hook/use-transformer.ts";
- import { getMouseColors } from "@/utils/colors";
- import {
- useCustomSnapInfos,
- useGlobalSnapInfos,
- useSnap,
- useSnapResultInfo,
- } from "@/core/hook/use-snap";
- import { generateSnapInfos } from "../util";
- import { ComponentSnapInfo } from "..";
- import { useShapeIsHover } from "@/core/hook/use-mouse-status";
- import { useCursor } from "@/core/hook/use-global-vars";
- import { mergeFuns, rangMod } from "@/utils/shared";
- import { Operate } from "../../html-mount/propertys/index.ts";
- import {
- useFixedScale,
- useViewer,
- useViewerInvertTransformConfig,
- } from "@/core/hook/use-viewer.ts";
- import { useMode } from "@/core/hook/use-status";
- import { Mode } from "@/constant/mode";
- const props = defineProps<{
- points: Pos[];
- ndx: number;
- id: string;
- color?: string;
- size?: number;
- fixed?: boolean;
- disable?: boolean;
- drawIng?: boolean;
- opacity?: number;
- closed?: boolean;
- notDelete?: boolean;
- getSelfSnapInfos?: (point: Pos) => ComponentSnapInfo[];
- }>();
- const emit = defineEmits<{
- (e: "update:position", position: Pos): void;
- (e: "dragend"): void;
- (e: "dragstart"): void;
- (e: "delete"): void;
- }>();
- const position = computed(() => props.points[props.ndx]);
- const scale = useFixedScale();
- const viewer = useViewer();
- const style = computed(() => {
- const color = getMouseColors(props.color || themeColor);
- let size = Math.max(props.size || 10, 10);
- size = props.fixed ? scale.value * size : size;
- return {
- radius: size / 2,
- fill: props.drawIng || isHover.value || dragIng.value ? "#fff" : color.pub,
- stroke: color.pub,
- strokeWidth: size / 4,
- opacity: props.opacity !== undefined ? props.opacity : props.disable ? 0.5 : 1,
- };
- });
- const infos = useCustomSnapInfos();
- const addedInfos = [] as ComponentSnapInfo[];
- const clearInfos = () => {
- addedInfos.forEach(infos.remove);
- };
- const startHandler = () => {
- viewer.disabled.value = true;
- clearInfos();
- const ndx = props.ndx;
- const geos = [
- props.points.slice(0, ndx),
- props.points.slice(ndx + 1, props.points.length),
- ];
- if (props.closed || (ndx > 0 && ndx < props.points.length - 1)) {
- const prev = rangMod(ndx - 1, props.points.length);
- const next = rangMod(ndx + 1, props.points.length);
- geos.push([props.points[prev], props.points[next]]);
- }
- 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);
- const circle = ref<DC<Circle>>();
- const offset = useShapeDrag(circle);
- const hResult = useShapeIsHover(circle);
- const isHover = hResult[0];
- const cursor = useCursor();
- const mode = useMode();
- const drawing = computed(() => mode.include(Mode.draw));
- watch(
- [isHover, drawing],
- ([hover, drawing], _, onCleanup) => {
- if (hover && !drawing) {
- onCleanup(cursor.push("./icons/m_move.png"));
- }
- },
- { immediate: true }
- );
- const dragIng = ref(false);
- let init: Pos;
- let onUmHooks: (() => void)[] = [];
- const resultInfo = useSnapResultInfo();
- watch(offset, (offset, oldOffsert) => {
- snap.clear();
- if (!oldOffsert) {
- init = { ...position.value };
- emit("dragstart");
- startHandler();
- dragIng.value = true;
- onUmHooks.push(() => {
- emit("dragend");
- clearInfos();
- dragIng.value = false;
- viewer.disabled.value = false;
- resultInfo.clear();
- });
- }
- if (offset) {
- const point = {
- x: init.x + offset.x,
- y: init.y + offset.y,
- };
- const refSnapInfos = props.getSelfSnapInfos
- ? props.getSelfSnapInfos(point)
- : generateSnapInfos([point], true, true);
- const transform = snap.move(refSnapInfos);
- emit("update:position", transform ? transform.point(point) : point);
- } else {
- mergeFuns(onUmHooks)();
- onUmHooks.length = 0;
- }
- });
- onUnmounted(() => mergeFuns(onUmHooks)());
- watch(
- () => props.disable,
- (disable) => {
- if (disable) {
- offset.pause();
- hResult.pause();
- } else {
- offset.resume();
- hResult.resume();
- }
- },
- { immediate: true }
- );
- defineExpose({
- get shape() {
- return circle.value;
- },
- });
- </script>
|