polygons.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import { PolygonsAttrib, PolygonsPointAttrib } from "@/request/type";
  2. import {
  3. incEntitysFactoryGenerate,
  4. Attrib,
  5. wholeLineStyle,
  6. getRealAbsoluteSize,
  7. PenEditWholeLine,
  8. WholeLinePoint,
  9. getWholeLinePolygonPoints,
  10. shapeParentsEq,
  11. openEntityDrag,
  12. WholeLineInc,
  13. wholeLineDelLineByPointIds,
  14. } from "drawing-board";
  15. import { Group } from "konva/lib/Group";
  16. import { Path } from "konva/lib/shapes/Path";
  17. import { Circle } from "konva/lib/shapes/Circle";
  18. import { Label, Tag } from "konva/lib/shapes/Label";
  19. import { Text } from "konva/lib/shapes/Text";
  20. import { ref } from "vue";
  21. import mitt from "mitt";
  22. import { point } from "@/submodule/src/board/packages/whole-line/style";
  23. // 加点
  24. const getPolygonPoint = (position: number[]) => {
  25. const pointAttrib = {
  26. rtk: false,
  27. title: "",
  28. x: position[0],
  29. y: position[1],
  30. };
  31. return pointAttrib;
  32. };
  33. const pointActShapeFactory = (attrib: PolygonsPointAttrib, tree: any) => {
  34. const polygons = tree.parent as Polygons;
  35. const size = { width: 43, height: 44 };
  36. const out = new Path({
  37. 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`,
  38. strokeScaleEnabled: true,
  39. stroke: "#ffffff",
  40. strokeWidth: 1,
  41. });
  42. const inner = new Path({
  43. fill: "#fff",
  44. 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`,
  45. });
  46. const rect = new Circle({
  47. name: "anchor-move",
  48. radius: Math.min(size.width, size.height) / 2,
  49. fill: "rgba(0, 0, 0, 0)",
  50. offset: { x: -size.width / 2, y: -size.height / 2 },
  51. });
  52. const wlp = wholeLineStyle.pointShapeFactory();
  53. point.radius = 5;
  54. point.hitStrokeWidth = point.strokeWidth = 4;
  55. wlp.shape.name("anchor-point");
  56. const index = new Text({
  57. name: "text",
  58. text: `1`,
  59. fontFamily: "Calibri",
  60. fontSize: 12,
  61. padding: 5,
  62. offsetY: -8,
  63. fill: "#000",
  64. });
  65. const label = new Label({
  66. visible: false,
  67. opacity: 0.75,
  68. name: "label",
  69. offsetX: -size.width / 2,
  70. offsetY: -6,
  71. });
  72. label.add(
  73. new Tag({
  74. name: "tag",
  75. fill: "rgba(255, 255, 255, 0.8)",
  76. pointerDirection: "down",
  77. pointerWidth: 5,
  78. pointerHeight: 5,
  79. lineJoin: "round",
  80. shadowColor: "black",
  81. shadowBlur: 10,
  82. shadowOffsetX: 10,
  83. shadowOffsetY: 10,
  84. shadowOpacity: 0.5,
  85. }),
  86. new Text({
  87. name: "text",
  88. text: attrib.title || `P${attrib.id}`,
  89. fontFamily: "Calibri",
  90. fontSize: 10,
  91. padding: 5,
  92. fill: "#000",
  93. })
  94. );
  95. const offsetGroup = new Group();
  96. offsetGroup.add(out, inner, rect, label, index);
  97. offsetGroup.x(-size.width / 2);
  98. offsetGroup.y(-size.height);
  99. const group = new Group();
  100. group.add(offsetGroup, wlp.shape);
  101. const activeNdx = () => {
  102. if (polygons.editPolygonId.value) {
  103. const points = getWholeLinePolygonPoints(
  104. polygons.attrib,
  105. polygons.editPolygonId.value
  106. ).map(({ id }) => id);
  107. const ndx = points.indexOf(attrib.id);
  108. return ndx;
  109. }
  110. return -1;
  111. };
  112. const setStyle = () => {
  113. let [width, height] = getRealAbsoluteSize(group, [1, 1]);
  114. group.scale({ x: width, y: height });
  115. const ndx = activeNdx();
  116. if (~ndx) {
  117. index.text((ndx + 1).toString()).visible(true);
  118. index.offsetX(-rect.width() / 2 + index.width() / 2);
  119. } else {
  120. index.visible(false);
  121. }
  122. };
  123. const commonStyle = () => {
  124. out.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF");
  125. label.visible(false);
  126. wlp.common();
  127. };
  128. const result = {
  129. shape: group,
  130. common: commonStyle,
  131. hover: () => {
  132. label.visible(true);
  133. },
  134. setData(data: number[]) {
  135. setStyle();
  136. group.x(data[0]);
  137. group.y(data[1]);
  138. label.visible(polygons.activePointId.value === attrib.id);
  139. },
  140. draging() {
  141. if (polygons.editPolygonId.value && !attrib.rtk) {
  142. out.fill("#e0403c");
  143. }
  144. },
  145. active() {
  146. polygons.activePointId.value = attrib.id;
  147. polygons.bus.emit("clickPoint", attrib);
  148. },
  149. };
  150. return result;
  151. };
  152. export class Polygons extends PenEditWholeLine<PolygonsAttrib & Attrib> {
  153. bus = mitt<{ clickPoint: PolygonsPointAttrib; penEndHandler: void }>();
  154. activePointId = ref<string>();
  155. dragAttach(inc: WholeLineInc<PolygonsAttrib & Attrib>) {
  156. inc.pointEntityInc.adds.forEach((point) => {
  157. openEntityDrag(point, {
  158. readyHandler: (attrib) => {
  159. return [attrib.x, attrib.y];
  160. },
  161. moveHandler: (pointAttrib, move) => {
  162. if (this.editPolygonId.value && !pointAttrib.rtk) {
  163. pointAttrib.x = move[0];
  164. pointAttrib.y = move[1];
  165. }
  166. },
  167. });
  168. point.enableMouseAct(point.actShape);
  169. });
  170. inc.lineEntityInc.adds.forEach((line) => {
  171. line.enableMouseAct(line.actShape);
  172. });
  173. inc.polygonEntityInc.adds.forEach((py) => {
  174. py.enableMouseAct(py.actShape);
  175. });
  176. }
  177. removePolygon(polygonId: string) {
  178. const ndx = this.attrib.polygons.findIndex(({ id }) => id === polygonId);
  179. if (!~ndx) {
  180. return;
  181. }
  182. const polygonLines = this.attrib.polygons[ndx].lineIds;
  183. let joinPointIds: string[] = [];
  184. while (polygonLines.length) {
  185. const ndx = this.attrib.lines.findIndex(
  186. ({ id }) => id === polygonLines[0]
  187. );
  188. if (~ndx) {
  189. joinPointIds.push(...this.attrib.lines[ndx].pointIds);
  190. this.attrib.lines.splice(ndx, 1);
  191. }
  192. polygonLines.shift();
  193. }
  194. joinPointIds = Array.from(new Set(joinPointIds));
  195. while (joinPointIds.length) {
  196. const ndx = this.attrib.points.findIndex(
  197. ({ id }) => id === joinPointIds[0]
  198. );
  199. if (~ndx && !this.attrib.points[ndx].rtk) {
  200. this.attrib.points.splice(ndx, 1);
  201. }
  202. joinPointIds.shift();
  203. }
  204. this.attrib.polygons.splice(ndx, 1);
  205. }
  206. initIncFactory() {
  207. super.initIncFactory();
  208. this.incPointsFactory = incEntitysFactoryGenerate(
  209. WholeLinePoint<any>,
  210. this,
  211. (point) => {
  212. point.actShapeFactory = pointActShapeFactory;
  213. }
  214. );
  215. }
  216. editPolygon(polygonId?: string) {
  217. super.enterEditMode({
  218. polygonId: polygonId,
  219. pointAttribFactory: getPolygonPoint,
  220. canOper: (tree, operShape) => {
  221. return (
  222. !tree.name.includes(WholeLinePoint.namespace) ||
  223. operShape.name() === "anchor-point"
  224. );
  225. },
  226. quitHandler: () => {
  227. this.bus.emit("penEndHandler");
  228. },
  229. canDelPoint: (p) => !p.rtk,
  230. quotePoint: false,
  231. });
  232. return super.leaveEditMode;
  233. }
  234. mounted(): void {
  235. super.mounted();
  236. let clearCursor: (() => void) | null = null;
  237. this.container.stage.on("mousemove.anchor-move", (evt) => {
  238. const isPoint = evt.target.name() === "anchor-move";
  239. if (!isPoint) {
  240. clearCursor && clearCursor();
  241. clearCursor = null;
  242. return;
  243. }
  244. if (this.editPolygonId.value) {
  245. clearCursor = this.container.setCursor("move");
  246. } else {
  247. clearCursor = this.container.setCursor("pointer");
  248. }
  249. });
  250. this.container.stage.on("click.anchor-move", (evt) => {
  251. const point = shapeParentsEq(evt.target, (shape) =>
  252. shape.id().startsWith(WholeLinePoint.namespace)
  253. );
  254. if (!point) {
  255. this.activePointId.value = undefined;
  256. }
  257. });
  258. }
  259. destory(): void {
  260. super.destory();
  261. this.container.stage.off("mousemove.anchor-move click.anchor-move");
  262. }
  263. }