import { PolygonsAttrib, PolygonsPointAttrib } from "./type"; import { incEntitysFactoryGenerate, Attrib, wholeLineStyle, getRealAbsoluteSize, PenEditWholeLine, WholeLinePoint, getWholeLinePolygonPoints, shapeParentsEq, openEntityDrag, WholeLineInc, } from "../../board"; import { Group } from "konva/lib/Group"; import { Path } from "konva/lib/shapes/Path"; import { Circle } from "konva/lib/shapes/Circle"; import { Label, Tag } from "konva/lib/shapes/Label"; import { Text } from "konva/lib/shapes/Text"; import { ref } from "vue"; import mitt from "mitt"; import { point } from "../../board/packages/whole-line/style"; // 加点 const getPolygonPoint = (position: number[]) => { const pointAttrib = { rtk: false, title: "", x: position[0], y: position[1], }; return pointAttrib; }; const pointActShapeFactory = (attrib: PolygonsPointAttrib, tree: any) => { const polygons = tree.parent as Polygons; const size = { width: 43, height: 44 }; const out = new Path({ 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`, strokeScaleEnabled: true, stroke: "#ffffff", strokeWidth: 1, }); const inner = new Path({ fill: "#fff", 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`, }); const rect = new Circle({ name: "anchor-move", radius: Math.min(size.width, size.height) / 2, fill: "rgba(0, 0, 0, 0)", offset: { x: -size.width / 2, y: -size.height / 2 }, }); const wlp = wholeLineStyle.pointShapeFactory(); point.radius = 5; point.hitStrokeWidth = point.strokeWidth = 4; wlp.shape.name("anchor-point"); const index = new Text({ name: "text", text: `1`, fontFamily: "Calibri", fontSize: 12, padding: 5, offsetY: -8, fill: "#000", }); const label = new Label({ visible: false, opacity: 0.75, name: "label", offsetX: -size.width / 2, offsetY: -6, }); label.add( new Tag({ name: "tag", fill: "rgba(255, 255, 255, 0.8)", pointerDirection: "down", pointerWidth: 5, pointerHeight: 5, lineJoin: "round", shadowColor: "black", shadowBlur: 10, shadowOffsetX: 10, shadowOffsetY: 10, shadowOpacity: 0.5, }), new Text({ name: "text", text: attrib.title || `P${attrib.id}`, fontFamily: "Calibri", fontSize: 10, padding: 5, fill: "#000", }) ); const offsetGroup = new Group(); offsetGroup.add(out, inner, rect, label, index); offsetGroup.x(-size.width / 2); offsetGroup.y(-size.height); const group = new Group(); group.add(offsetGroup, wlp.shape); const activeNdx = () => { if (polygons.editPolygonId.value) { const points = getWholeLinePolygonPoints( polygons.attrib, polygons.editPolygonId.value ).map(({ id }) => id); const ndx = points.indexOf(attrib.id); return ndx; } return -1; }; const setStyle = () => { let [width, height] = getRealAbsoluteSize(group, [1, 1]); group.scale({ x: width, y: height }); const ndx = activeNdx(); if (~ndx) { index.text((ndx + 1).toString()).visible(true); index.offsetX(-rect.width() / 2 + index.width() / 2); } else { index.visible(false); } }; const commonStyle = () => { out.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF"); label.visible(false); wlp.common(); }; const result = { shape: group, common: commonStyle, hover: () => { label.visible(true); }, setData(data: number[]) { setStyle(); group.x(data[0]); group.y(data[1]); label.visible(polygons.activePointId.value === attrib.id); }, draging() { if (polygons.editPolygonId.value && !attrib.rtk) { out.fill("#e0403c"); } }, active() { polygons.activePointId.value = attrib.id; polygons.bus.emit("clickPoint", attrib); }, }; return result; }; export class Polygons extends PenEditWholeLine { bus = mitt<{ clickPoint: PolygonsPointAttrib; penEndHandler: void }>(); activePointId = ref(); dragAttach(inc: WholeLineInc) { inc.pointEntityInc.adds.forEach((point) => { openEntityDrag(point, { readyHandler: (attrib) => { return [attrib.x, attrib.y]; }, moveHandler: (pointAttrib, move) => { if (this.editPolygonId.value && !pointAttrib.rtk) { pointAttrib.x = move[0]; pointAttrib.y = move[1]; } }, }); point.enableMouseAct(point.actShape); }); inc.lineEntityInc.adds.forEach((line) => { line.enableMouseAct(line.actShape); }); inc.polygonEntityInc.adds.forEach((py) => { py.enableMouseAct(py.actShape); }); } removePolygon(polygonId: string) { const ndx = this.attrib.polygons.findIndex(({ id }) => id === polygonId); if (!~ndx) { return; } const polygonLines = this.attrib.polygons[ndx].lineIds; let joinPointIds: string[] = []; while (polygonLines.length) { const ndx = this.attrib.lines.findIndex( ({ id }) => id === polygonLines[0] ); if (~ndx) { joinPointIds.push(...this.attrib.lines[ndx].pointIds); this.attrib.lines.splice(ndx, 1); } polygonLines.shift(); } joinPointIds = Array.from(new Set(joinPointIds)); while (joinPointIds.length) { const ndx = this.attrib.points.findIndex( ({ id }) => id === joinPointIds[0] ); if (~ndx && !this.attrib.points[ndx].rtk) { this.attrib.points.splice(ndx, 1); } joinPointIds.shift(); } this.attrib.polygons.splice(ndx, 1); } initIncFactory() { super.initIncFactory(); this.incPointsFactory = incEntitysFactoryGenerate( WholeLinePoint, this, (point) => { point.actShapeFactory = pointActShapeFactory as any; } ); } editPolygon(polygonId?: string) { this.activePointId.value = polygonId; super.enterEditMode({ polygonId: polygonId, pointAttribFactory: getPolygonPoint, canOper: (tree, operShape) => { return ( !tree.name.includes(WholeLinePoint.namespace) || operShape.name() === "anchor-point" ); }, quitHandler: () => { this.bus.emit("penEndHandler"); }, canDelPoint: (p) => !p.rtk, quotePoint: false, }); return super.leaveEditMode; } mounted(): void { super.mounted(); let clearCursor: (() => void) | null = null; this.container.stage.on("mousemove.anchor-move", (evt) => { const isPoint = evt.target.name() === "anchor-move"; if (!isPoint) { clearCursor && clearCursor(); clearCursor = null; return; } if (this.editPolygonId.value) { clearCursor = this.container.setCursor("move"); } else { clearCursor = this.container.setCursor("pointer"); } }); this.container.stage.on("click.anchor-move", (evt) => { const point = shapeParentsEq(evt.target, (shape) => shape.id().startsWith(WholeLinePoint.namespace) ); if (!point) { this.activePointId.value = undefined; } }); } destory(): void { super.destory(); this.container.stage.off("mousemove.anchor-move click.anchor-move"); } }