point.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import { Path } from "konva/lib/shapes/Path";
  2. import {
  3. CustomizeShape,
  4. WholeLinePoint,
  5. getRealAbsoluteSize,
  6. getWholeLinePolygonPoints,
  7. mergeFuns,
  8. openEntityDrag,
  9. wholeLineStyle,
  10. } from "../../board";
  11. import { PolygonsPointAttrib } from "./type";
  12. import { Group } from "konva/lib/Group";
  13. import { Text } from "konva/lib/shapes/Text";
  14. import { Circle } from "konva/lib/shapes/Circle";
  15. import { Polygons } from "./polygons";
  16. import { point } from "../../board/packages/whole-line/style";
  17. import { Label, Tag } from "konva/lib/shapes/Label";
  18. import { watch, watchEffect } from "vue";
  19. const pointActShapeFactory = (attrib: PolygonsPointAttrib, tree: PoPoint) => {
  20. const polygons = tree.parent as unknown as Polygons;
  21. const size = { width: 43, height: 44 };
  22. const out = new Path({
  23. data: `M22 44C32.6667 33.891 38 25.891 38 20C38 11.1634 30.8366 4 22 4C13.1634 4 6 11.1634 6 20C6 25.891 11.3333 33.891 22 44Z`,
  24. strokeScaleEnabled: true,
  25. stroke: "#ffffff",
  26. strokeWidth: 1,
  27. });
  28. const inner = new Path({
  29. fill: "#fff",
  30. data: `M22 30C27.5228 30 32 25.5228 32 20C32 14.4772 27.5228 10 22 10C16.4772 10 12 14.4772 12 20C12 25.5228 16.4772 30 22 30Z`,
  31. });
  32. const select = new Path({
  33. fill: "#409EFF",
  34. offset: {
  35. x: -5,
  36. y: -5,
  37. },
  38. data: `M20.5143 12.213C20.7983 12.497 20.7983 12.9575 20.5143 13.2415L15.2727 18.4831L11.8494 15.0597C11.5654 14.7757 11.5654 14.3152 11.8494 14.0312C12.1334 13.7472 12.5939 13.7472 12.8779 14.0312L15.2727 16.426L19.4857 12.213C19.7698 11.929 20.2302 11.929 20.5143 12.213Z`,
  39. });
  40. const rectGroup = new Group({
  41. name: "anchor-move",
  42. });
  43. const rect = new Circle({
  44. name: "anchor-move",
  45. radius: Math.min(size.width, size.height) / 2,
  46. fill: "rgba(0, 0, 0, 0)",
  47. offset: { x: -size.width / 2, y: -size.height / 2 },
  48. });
  49. const wlp = wholeLineStyle.pointShapeFactory();
  50. point.radius = 5;
  51. point.hitStrokeWidth = point.strokeWidth = 4;
  52. wlp.shape.name("anchor-point");
  53. const index = new Text({
  54. name: "text",
  55. text: `1`,
  56. fontFamily: "Calibri",
  57. fontSize: 12,
  58. padding: 5,
  59. offsetY: -8,
  60. fill: "#000",
  61. });
  62. const label = new Label({
  63. visible: false,
  64. opacity: 1,
  65. name: "label",
  66. offsetX: -size.width / 2,
  67. offsetY: -6,
  68. });
  69. rectGroup.add(index, label, rect);
  70. const text = new Text({
  71. name: "text",
  72. text: attrib.title || `P${attrib.id}`,
  73. fontFamily: "Inter",
  74. fontSize: 12,
  75. padding: 8,
  76. fill: "#303133",
  77. });
  78. label.add(
  79. new Tag({
  80. name: "tag",
  81. fill: "rgba(255, 255, 255, 1)",
  82. pointerDirection: "down",
  83. pointerWidth: 8,
  84. pointerHeight: 8,
  85. lineJoin: "round",
  86. shadowColor: "black",
  87. cornerRadius: 2,
  88. opacity: 1,
  89. shadowBlur: 10,
  90. shadowOffsetX: 10,
  91. shadowOffsetY: 10,
  92. shadowOpacity: 0.5,
  93. }),
  94. text
  95. );
  96. const offsetGroup = new Group();
  97. offsetGroup.add(out, inner, select, rectGroup);
  98. offsetGroup.x(-size.width / 2);
  99. offsetGroup.y(-size.height);
  100. const group = new Group();
  101. group.add(offsetGroup, wlp.shape);
  102. const result = {
  103. shape: group,
  104. common() {
  105. out.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF");
  106. select.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF");
  107. wlp.common();
  108. label.visible(false);
  109. },
  110. hover: () => {
  111. label.visible(true);
  112. if (!attrib.rtk) {
  113. out.fill("#409EFF");
  114. select.fill("#409EFF");
  115. }
  116. },
  117. setData(data: number[]) {
  118. let [width, height] = getRealAbsoluteSize(group, [1, 1]);
  119. group.scale({ x: width, y: height });
  120. group.x(data[0]);
  121. group.y(data[1]);
  122. text.text(tree.attrib.title || `P${attrib.id}`);
  123. if (~tree.editPolygonNdx) {
  124. index.text((tree.editPolygonNdx + 1).toString()).visible(true);
  125. index.offsetX(-rect.width() / 2 + index.width() / 2);
  126. wlp.shape.visible(true);
  127. select.visible(false);
  128. } else {
  129. index.visible(false);
  130. wlp.shape.visible(false);
  131. select.visible(polygons.status.selectPoiIds.includes(attrib.id));
  132. }
  133. },
  134. draging() {
  135. if (~tree.editPolygonNdx) {
  136. out.fill("#e0403c");
  137. select.fill("#e0403c");
  138. }
  139. },
  140. };
  141. return result;
  142. };
  143. export class PoPoint extends WholeLinePoint<PolygonsPointAttrib, Group> {
  144. actShape: CustomizeShape<number[], Group, { setNdx: (ndx: number) => void }> =
  145. null;
  146. get editPolygonNdx() {
  147. const polygons = this.parent as unknown as Polygons;
  148. if (polygons.status.editPolygonId) {
  149. const points = getWholeLinePolygonPoints(
  150. polygons.attrib,
  151. polygons.status.editPolygonId
  152. ).map(({ id }) => id);
  153. return points.indexOf(this.attrib.id);
  154. }
  155. return -1;
  156. }
  157. init(): void {
  158. this.actShapeFactory = pointActShapeFactory;
  159. super.init();
  160. this.enableMouseAct(this.actShape);
  161. }
  162. protected initReactive() {
  163. const polygons = this.parent as unknown as Polygons;
  164. this.bus.on("shapeStatusChange", ({ current, type }) => {
  165. if (current === "active" && type === "click") {
  166. polygons.bus.emit("clickPoint", this.attrib);
  167. }
  168. });
  169. return mergeFuns(
  170. super.initReactive(),
  171. watch(
  172. () => this.editPolygonNdx,
  173. (endx, _, onCleanup) => {
  174. if (!~endx || this.attrib.rtk) {
  175. return onCleanup(() => {});
  176. }
  177. const anchor = this.shape.findOne<Group>(".anchor-move");
  178. let clearCursor: (() => void) | null = null;
  179. anchor.on("mouseenter.anchor", () => {
  180. clearCursor && clearCursor();
  181. clearCursor = this.container.setCursor("move");
  182. });
  183. anchor.on("mouseleave.anchor", () => {
  184. clearCursor && clearCursor();
  185. clearCursor = null;
  186. });
  187. openEntityDrag(this, {
  188. readyHandler: (attrib) => {
  189. return [attrib.x, attrib.y];
  190. },
  191. moveHandler: (pointAttrib, move) => {
  192. if (~this.editPolygonNdx) {
  193. pointAttrib.x = move[0];
  194. pointAttrib.y = move[1];
  195. }
  196. },
  197. });
  198. onCleanup(() => {
  199. anchor.off("mouseenter.anchor mouseleave.anchor");
  200. clearCursor && clearCursor();
  201. this.disableDrag();
  202. });
  203. },
  204. { immediate: true }
  205. ),
  206. watchEffect(
  207. () => {
  208. if (polygons.status.lightPointId === this.attrib.id) {
  209. this.bus.emit("statusChange", { hover: true });
  210. } else {
  211. this.bus.emit("statusChange", null);
  212. }
  213. },
  214. { flush: "post" }
  215. )
  216. );
  217. }
  218. }