edit-point.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <v-circle
  3. :config="{ ...style, ...position, hitStrokeWidth: style.strokeWidth }"
  4. ref="circle"
  5. />
  6. <Operate :target="circle" :menus="[{ label: '删除', handler: () => emit('delete') }]" />
  7. </template>
  8. <script lang="ts" setup>
  9. import { Pos } from "@/utils/math.ts";
  10. import { themeColor } from "@/constant";
  11. import { computed, ref, watch } from "vue";
  12. import { DC } from "@/deconstruction";
  13. import { Circle } from "konva/lib/shapes/Circle";
  14. import { useShapeDrag } from "@/core/hook/use-transformer.ts";
  15. import { getMouseColors } from "@/utils/colors";
  16. import { useCustomSnapInfos, useGlobalSnapInfos, useSnap } from "@/core/hook/use-snap";
  17. import { generateSnapInfos } from "../util";
  18. import { ComponentSnapInfo } from "..";
  19. import { useShapeIsHover } from "@/core/hook/use-mouse-status";
  20. import { useCursor } from "@/core/hook/use-global-vars";
  21. import { rangMod } from "@/utils/shared";
  22. import { Operate } from "../../html-mount/propertys/index.ts";
  23. const props = defineProps<{
  24. points: Pos[];
  25. ndx: number;
  26. id: string;
  27. color?: string;
  28. size?: number;
  29. disable?: boolean;
  30. opacity?: number;
  31. closed?: boolean;
  32. notDelete?: boolean;
  33. getSelfSnapInfos?: (point: Pos) => ComponentSnapInfo[];
  34. }>();
  35. const emit = defineEmits<{
  36. (e: "update:position", position: Pos): void;
  37. (e: "dragend"): void;
  38. (e: "dragstart"): void;
  39. (e: "delete"): void;
  40. }>();
  41. const position = computed(() => props.points[props.ndx]);
  42. const style = computed(() => {
  43. const color = getMouseColors(props.color || themeColor);
  44. const size = props.size || 5;
  45. return {
  46. radius: size / 2,
  47. fill: isHover.value || dragIng.value ? "#fff" : color.pub,
  48. stroke: color.pub,
  49. strokeWidth: size / 4,
  50. opacity: props.opacity !== undefined ? props.opacity : props.disable ? 0.5 : 1,
  51. };
  52. });
  53. const infos = useCustomSnapInfos();
  54. const addedInfos = [] as ComponentSnapInfo[];
  55. const clearInfos = () => {
  56. addedInfos.forEach(infos.remove);
  57. };
  58. const startHandler = () => {
  59. clearInfos();
  60. const ndx = props.ndx;
  61. const geos = [
  62. props.points.slice(0, ndx),
  63. props.points.slice(ndx + 1, props.points.length),
  64. ];
  65. if (props.closed || (ndx > 0 && ndx < props.points.length - 1)) {
  66. const prev = rangMod(ndx - 1, props.points.length);
  67. const next = rangMod(ndx + 1, props.points.length);
  68. geos.push([props.points[prev], props.points[next]]);
  69. }
  70. geos.forEach((geo) => {
  71. const snapInfos = generateSnapInfos(geo, true, true, true);
  72. snapInfos.forEach((item) => {
  73. infos.add(item);
  74. addedInfos.push(item);
  75. });
  76. });
  77. };
  78. const snapInfos = useGlobalSnapInfos();
  79. const refSnapInfos = computed(() => {
  80. if (!props.id) {
  81. return snapInfos.value;
  82. } else {
  83. return snapInfos.value.filter((p) => !("id" in p) || p.id !== props.id);
  84. }
  85. });
  86. const snap = useSnap(refSnapInfos);
  87. const circle = ref<DC<Circle>>();
  88. const offset = useShapeDrag(circle);
  89. const hResult = useShapeIsHover(circle);
  90. const isHover = hResult[0];
  91. const cursor = useCursor();
  92. if (!props.notDelete) {
  93. watch(
  94. isHover,
  95. (hover, _, onCleanup) => {
  96. if (hover) {
  97. onCleanup(cursor.push("/icons/m_move.png"));
  98. }
  99. },
  100. { immediate: true }
  101. );
  102. }
  103. const dragIng = ref(false);
  104. let init: Pos;
  105. watch(offset, (offset, oldOffsert) => {
  106. snap.clear();
  107. if (!oldOffsert) {
  108. init = { ...position.value };
  109. startHandler();
  110. emit("dragstart");
  111. cursor.push("/icons/m_move.png");
  112. dragIng.value = true;
  113. }
  114. if (offset) {
  115. const point = {
  116. x: init.x + offset.x,
  117. y: init.y + offset.y,
  118. };
  119. const refSnapInfos = props.getSelfSnapInfos
  120. ? props.getSelfSnapInfos(point)
  121. : generateSnapInfos([point], true, true);
  122. // console.log(refSnapInfos);
  123. const transform = snap.move(refSnapInfos);
  124. emit("update:position", transform ? transform.point(point) : point);
  125. } else {
  126. emit("dragend");
  127. cursor.pop();
  128. clearInfos();
  129. dragIng.value = false;
  130. }
  131. });
  132. watch(
  133. () => props.disable,
  134. (disable) => {
  135. if (disable) {
  136. offset.pause();
  137. hResult.pause();
  138. } else {
  139. offset.resume();
  140. hResult.resume();
  141. }
  142. },
  143. { immediate: true }
  144. );
  145. defineExpose({
  146. get shape() {
  147. return circle.value;
  148. },
  149. });
  150. </script>