aldehyde 0.2.494 → 0.2.495

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +63 -63
  2. package/lib/draw-canvas-edit/components/asset-bar/index.less +35 -35
  3. package/lib/draw-canvas-edit/components/main-header/index.less +23 -23
  4. package/lib/layout2/page.d.ts +2 -1
  5. package/lib/layout2/page.d.ts.map +1 -1
  6. package/lib/layout2/page.js +19 -8
  7. package/lib/layout2/page.js.map +1 -1
  8. package/lib/layout2/type/layout-type.d.ts +1 -0
  9. package/lib/layout2/type/layout-type.d.ts.map +1 -1
  10. package/lib/lowcode-components/base-table/index.less +61 -61
  11. package/lib/lowcode-components/base-text/index.less +19 -19
  12. package/lib/lowcode-components/data-number/index.less +10 -10
  13. package/lib/lowcode-components/date-time/index.less +4 -4
  14. package/lib/lowcode-components/four-angle-glow-border/index.less +49 -49
  15. package/lib/lowcode-components/lowcode-view/component/font/FontGlobal.css +26 -26
  16. package/lib/lowcode-components/lowcode-view/component/screen-fit/index.less +13 -13
  17. package/lib/lowcode-components/text-scroller/index.less +28 -28
  18. package/lib/module/ltmpl-table.d.ts +7 -0
  19. package/lib/module/ltmpl-table.d.ts.map +1 -1
  20. package/lib/module/ltmpl-table.js +12 -16
  21. package/lib/module/ltmpl-table.js.map +1 -1
  22. package/lib/routable/dtmpl-route.d.ts.map +1 -1
  23. package/lib/routable/dtmpl-route.js +8 -2
  24. package/lib/routable/dtmpl-route.js.map +1 -1
  25. package/lib/routable/import-route.d.ts.map +1 -1
  26. package/lib/routable/import-route.js +9 -1
  27. package/lib/routable/import-route.js.map +1 -1
  28. package/lib/routable/ltmpl-route.d.ts.map +1 -1
  29. package/lib/routable/ltmpl-route.js +13 -6
  30. package/lib/routable/ltmpl-route.js.map +1 -1
  31. package/lib/routable/splitview-ltmpl-route.d.ts.map +1 -1
  32. package/lib/routable/splitview-ltmpl-route.js +11 -10
  33. package/lib/routable/splitview-ltmpl-route.js.map +1 -1
  34. package/lib/routable/ttmpl-route.d.ts.map +1 -1
  35. package/lib/routable/ttmpl-route.js +9 -2
  36. package/lib/routable/ttmpl-route.js.map +1 -1
  37. package/lib/table/act-table.d.ts +1 -0
  38. package/lib/table/act-table.d.ts.map +1 -1
  39. package/lib/table/act-table.js +31 -9
  40. package/lib/table/act-table.js.map +1 -1
  41. package/lib/table/page-chart.js +1 -1
  42. package/lib/table/page-chart.js.map +1 -1
  43. package/lib/table/row-table.d.ts +6 -0
  44. package/lib/table/row-table.d.ts.map +1 -1
  45. package/lib/table/row-table.js +21 -6
  46. package/lib/table/row-table.js.map +1 -1
  47. package/lib/tmpl/interface.d.ts +1 -0
  48. package/lib/tmpl/interface.d.ts.map +1 -1
  49. package/lib/tree/act-tree.d.ts +1 -0
  50. package/lib/tree/act-tree.d.ts.map +1 -1
  51. package/lib/tree/act-tree.js +6 -7
  52. package/lib/tree/act-tree.js.map +1 -1
  53. package/lib/tree/tree-utils.d.ts +1 -1
  54. package/lib/tree/tree-utils.d.ts.map +1 -1
  55. package/lib/tree/tree-utils.js +4 -4
  56. package/lib/tree/tree-utils.js.map +1 -1
  57. package/lib/units/index.d.ts +4 -0
  58. package/lib/units/index.d.ts.map +1 -1
  59. package/lib/units/index.js +10 -3
  60. package/lib/units/index.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +63 -63
  63. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +93 -93
  64. package/src/aldehyde/draw-canvas-edit/components/asset-bar/index.less +35 -35
  65. package/src/aldehyde/draw-canvas-edit/components/asset-bar/index.tsx +110 -110
  66. package/src/aldehyde/draw-canvas-edit/components/main-header/index.less +23 -23
  67. package/src/aldehyde/draw-canvas-edit/components/main-header/index.tsx +263 -263
  68. package/src/aldehyde/draw-canvas-edit/components/render/draws/index.ts +7 -7
  69. package/src/aldehyde/draw-canvas-edit/components/render/graphs/base-graph.ts +241 -241
  70. package/src/aldehyde/draw-canvas-edit/components/render/graphs/circle.ts +699 -699
  71. package/src/aldehyde/draw-canvas-edit/components/render/graphs/curve.ts +500 -500
  72. package/src/aldehyde/draw-canvas-edit/components/render/graphs/index.ts +5 -5
  73. package/src/aldehyde/draw-canvas-edit/components/render/graphs/line.ts +493 -493
  74. package/src/aldehyde/draw-canvas-edit/components/render/graphs/rect.ts +680 -680
  75. package/src/aldehyde/draw-canvas-edit/components/render/handlers/drag-handlers.ts +68 -68
  76. package/src/aldehyde/draw-canvas-edit/components/render/handlers/graph-handlers.ts +113 -113
  77. package/src/aldehyde/draw-canvas-edit/components/render/handlers/index.ts +9 -9
  78. package/src/aldehyde/draw-canvas-edit/components/render/handlers/key-move-handlers.ts +49 -49
  79. package/src/aldehyde/draw-canvas-edit/components/render/handlers/link-handlers.ts +45 -45
  80. package/src/aldehyde/draw-canvas-edit/components/render/handlers/shutcut-handlers.ts +45 -45
  81. package/src/aldehyde/draw-canvas-edit/components/render/handlers/text-handlers.ts +81 -81
  82. package/src/aldehyde/draw-canvas-edit/components/render/handlers/zoom-handlers.ts +59 -59
  83. package/src/aldehyde/draw-canvas-edit/components/render/tools/align-tool.ts +89 -89
  84. package/src/aldehyde/draw-canvas-edit/components/render/tools/asset-tool.ts +154 -154
  85. package/src/aldehyde/draw-canvas-edit/components/render/tools/link-tool.ts +222 -222
  86. package/src/aldehyde/draw-canvas-edit/components/render/tools/z-index-tool.ts +224 -224
  87. package/src/aldehyde/draw-canvas-edit/components/render/utils/a-star.ts +116 -116
  88. package/src/aldehyde/draw-canvas-edit/components/render/utils/bezier-scene-func.ts +72 -72
  89. package/src/aldehyde/draw-canvas-edit/components/setting-form/imag-upload.tsx +119 -119
  90. package/src/aldehyde/layout2/page.tsx +17 -9
  91. package/src/aldehyde/layout2/type/layout-type.ts +1 -0
  92. package/src/aldehyde/layout4/imgs/user.svg +26 -26
  93. package/src/aldehyde/lowcode-components/base-color-block/index.tsx +31 -31
  94. package/src/aldehyde/lowcode-components/base-table/index.less +61 -61
  95. package/src/aldehyde/lowcode-components/base-text/index.less +19 -19
  96. package/src/aldehyde/lowcode-components/data-number/index.less +10 -10
  97. package/src/aldehyde/lowcode-components/date-time/index.less +4 -4
  98. package/src/aldehyde/lowcode-components/date-time/index.tsx +64 -64
  99. package/src/aldehyde/lowcode-components/four-angle-glow-border/index.less +49 -49
  100. package/src/aldehyde/lowcode-components/four-angle-glow-border/index.tsx +53 -53
  101. package/src/aldehyde/lowcode-components/lowcode-view/component/abstract-controller.ts +64 -64
  102. package/src/aldehyde/lowcode-components/lowcode-view/component/abstract-definition.ts +77 -77
  103. package/src/aldehyde/lowcode-components/lowcode-view/component/abstract-designer-loader.ts +36 -36
  104. package/src/aldehyde/lowcode-components/lowcode-view/component/component-container.tsx +91 -91
  105. package/src/aldehyde/lowcode-components/lowcode-view/component/font/FontGlobal.css +26 -26
  106. package/src/aldehyde/lowcode-components/lowcode-view/component/group-layer/controller.ts +36 -36
  107. package/src/aldehyde/lowcode-components/lowcode-view/component/group-layer/definition.ts +53 -53
  108. package/src/aldehyde/lowcode-components/lowcode-view/component/group-layer/index.tsx +15 -15
  109. package/src/aldehyde/lowcode-components/lowcode-view/component/layer-builder.tsx +98 -98
  110. package/src/aldehyde/lowcode-components/lowcode-view/component/screen-fit/index.less +13 -13
  111. package/src/aldehyde/lowcode-components/lowcode-view/component/screen-fit/index.tsx +121 -121
  112. package/src/aldehyde/lowcode-components/placeholder-component/index.tsx +81 -81
  113. package/src/aldehyde/lowcode-components/text-scroller/index.less +28 -28
  114. package/src/aldehyde/lowcode-components/text-scroller/index.tsx +173 -173
  115. package/src/aldehyde/module/ltmpl-table.tsx +14 -15
  116. package/src/aldehyde/routable/dtmpl-route.tsx +14 -8
  117. package/src/aldehyde/routable/import-route.tsx +12 -5
  118. package/src/aldehyde/routable/ltmpl-route.tsx +14 -9
  119. package/src/aldehyde/routable/splitview-ltmpl-route.tsx +11 -8
  120. package/src/aldehyde/routable/ttmpl-route.tsx +13 -8
  121. package/src/aldehyde/table/act-table.tsx +28 -9
  122. package/src/aldehyde/table/page-chart.tsx +1 -1
  123. package/src/aldehyde/table/row-table.tsx +29 -6
  124. package/src/aldehyde/tmpl/interface.tsx +1 -0
  125. package/src/aldehyde/tree/act-tree.tsx +8 -6
  126. package/src/aldehyde/tree/tree-utils.tsx +4 -4
  127. package/src/aldehyde/units/index.tsx +11 -3
@@ -1,494 +1,494 @@
1
- import Konva from 'konva';
2
- import { GraphAnchor, Render, AssetInfoPoint, LineManualPoint } from '../types';
3
- import { GraphDraw, LinkDraw, PreviewDraw } from '../draws';
4
- import { BaseGraph } from './base-graph';
5
-
6
- /**
7
- * 直线、折线
8
- */
9
- export class Line extends BaseGraph {
10
- // 实现:更新 图形 的 调整点 的 锚点位置
11
- static override updateAnchorShadows(graph: Konva.Group, anchorShadows: Konva.Circle[], shape?: Konva.Line): void {
12
- if (shape) {
13
- const points = shape.points();
14
- for (const shadow of anchorShadows) {
15
- switch (shadow.attrs.adjustType) {
16
- case 'start':
17
- shadow.position({ x: points[0], y: points[1] });
18
- break;
19
- case 'end':
20
- shadow.position({ x: points[points.length - 2], y: points[points.length - 1] });
21
- break;
22
- }
23
- }
24
- }
25
- }
26
-
27
- // 实现:更新 图形 的 连接点 的 锚点位置
28
- static override updateLinkAnchorShadows(graph: Konva.Group, linkAnchorShadows: Konva.Circle[], shape?: Konva.Line): void {
29
- if (shape) {
30
- const points = shape.points();
31
- for (const shadow of linkAnchorShadows) {
32
- switch (shadow.attrs.alias) {
33
- case 'start':
34
- shadow.position({ x: points[0], y: points[1] });
35
- break;
36
- case 'end':
37
- shadow.position({ x: points[points.length - 2], y: points[points.length - 1] });
38
- break;
39
- }
40
- }
41
- }
42
- }
43
-
44
- static calculateAngle(sideA: number, sideB: number) {
45
- if (!isNaN(sideA) && !isNaN(sideB)) {
46
- const angleInRadians = Math.atan2(sideA, sideB);
47
- const angleInDegrees = angleInRadians * (180 / Math.PI);
48
- return angleInDegrees;
49
- }
50
- return 0;
51
- }
52
-
53
- // 实现:生成 调整点
54
- static override createAnchorShapes(
55
- render: Render,
56
- graph: Konva.Group,
57
- anchorAndShadows: {
58
- anchor: GraphAnchor;
59
- anchorShadow: Konva.Circle;
60
- shape?: Konva.Shape;
61
- }[],
62
- // eslint-disable-next-line
63
- adjustAnchor?: GraphAnchor
64
- ): {
65
- anchorAndShadows: {
66
- anchor: GraphAnchor;
67
- anchorShadow: Konva.Circle;
68
- shape?: Konva.Shape | undefined;
69
- }[]
70
- } {
71
- const stageState = render.getStageState();
72
- const graphShape = graph.findOne('.graph') as Konva.Line;
73
- if (graphShape) {
74
- const points = graphShape.points();
75
- for (const anchorAndShadow of anchorAndShadows) {
76
- let rotate = 0;
77
- const { anchor, anchorShadow } = anchorAndShadow;
78
- const x = render.toStageValue(anchorShadow.getAbsolutePosition().x - stageState.x),
79
- y = render.toStageValue(anchorShadow.getAbsolutePosition().y - stageState.y);
80
- if (anchor.adjustType === 'manual') {
81
- const anchorShape = new Konva.Circle({
82
- name: 'anchor',
83
- anchor: anchor,
84
- fill: anchor.adjusted ? `rgba(0,0,0,0.4)` : `rgba(0,0,255,0.4)`,
85
- radius: render.toStageValue(5),
86
- strokeWidth: 0,
87
- x: x,
88
- y: y,
89
- rotation: graph.getAbsoluteRotation(),
90
- visible: graph.attrs.adjusting || graph.attrs.hover === true
91
- });
92
- anchorShape.on('mouseenter', () => {
93
- document.body.style.cursor = 'move';
94
- graph.setAttr('hover', true);
95
- graph.setAttr('hoverAnchor', true);
96
- });
97
- anchorShape.on('mouseleave', () => {
98
- document.body.style.cursor = anchorShape.attrs.adjusting ? 'move' : 'default';
99
- graph.setAttr('hover', false);
100
- graph.setAttr('hoverAnchor', false);
101
- render.redraw([GraphDraw.NAME]);
102
- });
103
- anchorAndShadow.shape = anchorShape;
104
- } else {
105
- if (anchor.adjustType === 'start') {
106
- rotate = Line.calculateAngle(points[2] - points[0], points[3] - points[1]);
107
- } else if (anchor.adjustType === 'end') {
108
- rotate = Line.calculateAngle(points[points.length - 2] - points[points.length - 4], points[points.length - 1] - points[points.length - 3]);
109
- }
110
- const cos = Math.cos((rotate * Math.PI) / 180);
111
- const sin = Math.sin((rotate * Math.PI) / 180);
112
- const offset = render.toStageValue(render.pointSize - 20);
113
- const offsetX = offset * sin;
114
- const offsetY = offset * cos;
115
- const anchorShape = new Konva.Circle({
116
- name: 'anchor',
117
- anchor: anchor,
118
- fill: `rgba(0,0,255,0.4)`,
119
- radius: render.toStageValue(5),
120
- strokeWidth: 0,
121
- x: x,
122
- y: y,
123
- offsetX: anchor.adjustType === 'start' ? offsetX : anchor.adjustType === 'end' ? -offsetX : 0,
124
- offsetY: anchor.adjustType === 'start' ? offsetY : anchor.adjustType === 'end' ? -offsetY : 0,
125
- rotation: graph.getAbsoluteRotation(),
126
- visible: graph.attrs.adjusting || graph.attrs.hover === true
127
- });
128
- anchorShape.on('mouseenter', () => {
129
- document.body.style.cursor = 'move';
130
- graph.setAttr('hover', true);
131
- graph.setAttr('hoverAnchor', true);
132
- });
133
- anchorShape.on('mouseleave', () => {
134
- document.body.style.cursor = anchorShape.attrs.adjusting ? 'move' : 'default';
135
- graph.setAttr('hover', false);
136
- graph.setAttr('hoverAnchor', false);
137
- render.redraw([GraphDraw.NAME]);
138
- });
139
- anchorAndShadow.shape = anchorShape;
140
- }
141
- }
142
- }
143
- return { anchorAndShadows };
144
- }
145
-
146
- /**
147
- * 矩阵变换:坐标系中的一个点,围绕着另外一个点进行旋转
148
- * - - - - - - - -
149
- * |x`| |cos -sin| |x-a| |a|
150
- * | | = | | | | +
151
- * |y`| |sin cos| |y-b| |b|
152
- * - - - - - - - -
153
- * @param x 目标节点坐标 x
154
- * @param y 目标节点坐标 y
155
- * @param centerX 围绕的点坐标 x
156
- * @param centerY 围绕的点坐标 y
157
- * @param angle 旋转角度
158
- * @returns
159
- */
160
- static rotatePoint(x: number, y: number, centerX: number, centerY: number, angle: number) {
161
- const radians = (angle * Math.PI) / 180;
162
- const newX = Math.cos(radians) * (x - centerX) - Math.sin(radians) * (y - centerY) + centerX;
163
- const newY = Math.sin(radians) * (x - centerX) + Math.cos(radians) * (y - centerY) + centerY;
164
- return { x: newX, y: newY };
165
- }
166
-
167
- // 实现:调整 图形
168
- static override adjust(
169
- render: Render,
170
- graph: Konva.Group,
171
- graphSnap: Konva.Group,
172
- adjustShape: Konva.Shape,
173
- anchorAndShadows: {
174
- anchor: GraphAnchor;
175
- anchorShadow: Konva.Circle;
176
- shape?: Konva.Shape | undefined;
177
- }[],
178
- startPoint: Konva.Vector2d,
179
- endPoint: Konva.Vector2d,
180
- hoverRect?: Konva.Rect
181
- ) {
182
- // 目标 直线、折线
183
- const line = graph.findOne('.graph') as Konva.Line;
184
- const lineSnap = graphSnap.findOne('.graph') as Konva.Line;
185
- const anchors = (graph.find('.anchor') ?? []) as Konva.Circle[];
186
- const anchorsSnap = (graphSnap.find('.anchor') ?? []) as Konva.Circle[];
187
- const linkAnchors = (graph.find('.link-anchor') ?? []) as Konva.Circle[];
188
- if (line && lineSnap) {
189
- const stageState = render.getStageState();
190
- {
191
- const [graphRotation, adjustType, ex, ey] = [
192
- Math.round(graph.rotation()),
193
- adjustShape.attrs.anchor?.adjustType,
194
- endPoint.x,
195
- endPoint.y
196
- ];
197
- const { x: cx, y: cy, width: cw, height: ch } = graphSnap.getClientRect();
198
- const { x, y } = graph.position();
199
- const [centerX, centerY] = [cx + cw / 2, cy + ch / 2];
200
- const { x: sx, y: sy } = Line.rotatePoint(ex, ey, centerX, centerY, -graphRotation);
201
- const { x: rx, y: ry } = Line.rotatePoint(x, y, centerX, centerY, -graphRotation);
202
- const points = line.points();
203
- const manualPoints = (line.attrs.manualPoints ?? []) as LineManualPoint[];
204
- if (adjustType === 'manual') {
205
- if (adjustShape.attrs.anchor?.manualIndex !== void 0) {
206
- const index = adjustShape.attrs.anchor?.adjusted ? adjustShape.attrs.anchor?.manualIndex : adjustShape.attrs.anchor?.manualIndex + 1;
207
- const manualPointIndex = manualPoints.findIndex((o) => o.index === index);
208
- if (manualPointIndex > -1) {
209
- manualPoints[manualPointIndex].x = (sx - rx) / graph.scaleX();
210
- manualPoints[manualPointIndex].y = (sy - ry) / graph.scaleY();
211
- }
212
- const linkPoints = [
213
- [points[0], points[1]],
214
- ...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),
215
- [points[points.length - 2], points[points.length - 1]]
216
- ];
217
- line.setAttr('manualPoints', manualPoints);
218
- line.points(linkPoints.flat());
219
- const adjustAnchorShadow = anchors.find((o) => o.attrs.adjustType === 'manual' && o.attrs.manualIndex === index);
220
- if (adjustAnchorShadow) {
221
- adjustAnchorShadow.position({
222
- x: (sx - rx) / graph.scaleX(),
223
- y: (sy - ry) / graph.scaleY()
224
- });
225
- }
226
- }
227
- } else {
228
- const anchor = anchors.find((o) => o.attrs.adjustType === adjustType);
229
- const anchorShadow = anchorsSnap.find((o) => o.attrs.adjustType === adjustType);
230
- if (anchor && anchorShadow) {
231
- const linkPoints = [
232
- [points[0], points[1]],
233
- ...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),
234
- [points[points.length - 2], points[points.length - 1]]
235
- ];
236
- switch (adjustType) {
237
- case 'start':
238
- linkPoints[0] = [(sx - rx) / graph.scaleX(), (sy - ry) / graph.scaleY()];
239
- line.points(linkPoints.flat());
240
- break;
241
- case 'end':
242
- linkPoints[linkPoints.length - 1] = [(sx - rx) / graph.scaleX(), (sy - ry) / graph.scaleY()];
243
- line.points(linkPoints.flat());
244
- break;
245
- }
246
- }
247
- }
248
- }
249
- Line.updateAnchor(render, graph); // 更新 调整点(拐点)
250
- Line.updateAnchorShadows(graph, anchors, line); // 更新 调整点 的 锚点 位置
251
- Line.updateLinkAnchorShadows(graph, linkAnchors, line); // 更新 图形 的 连接点 的 锚点位置
252
- for (const anchor of anchors) {
253
- for (const { shape } of anchorAndShadows) {
254
- if (shape) {
255
- if (shape.attrs.anchor?.adjustType === anchor.attrs.adjustType) {
256
- const anchorShadow = graph.find(`.anchor`).find((o) => o.attrs.adjustType === anchor.attrs.adjustType);
257
- if (anchorShadow) {
258
- shape.position({
259
- x: render.toStageValue(anchorShadow.getAbsolutePosition().x - stageState.x),
260
- y: render.toStageValue(anchorShadow.getAbsolutePosition().y - stageState.y)
261
- });
262
- shape.rotation(graph.getAbsoluteRotation());
263
- }
264
- }
265
- }
266
- }
267
- }
268
- render.redraw([GraphDraw.NAME, LinkDraw.NAME, PreviewDraw.NAME]);
269
- }
270
- BaseGraph.adjust(
271
- render,
272
- graph,
273
- graphSnap,
274
- adjustShape,
275
- anchorAndShadows,
276
- startPoint,
277
- endPoint,
278
- hoverRect,
279
- line.size(),
280
- {
281
- x: Math.min(...line.points().reduce((arr, item, idx) => {
282
- if (idx % 2 === 0) arr.push(item);
283
- return arr;
284
- }, [] as number[])),
285
- y: Math.min(...line.points().reduce((arr, item, idx) => {
286
- if (idx % 2 === 1) arr.push(item);
287
- return arr;
288
- }, [] as number[]))
289
- }
290
- );
291
- }
292
-
293
- /**
294
- * 提供给 GraphDraw draw 使用
295
- */
296
- static override draw(graph: Konva.Group, render: Render, adjustAnchor?: GraphAnchor) {
297
- const anchors = (graph.attrs.anchors ?? []) as (GraphAnchor & { manualIndex?: number; adjusted?: boolean })[];
298
- const anchorShapes = graph.find(`.anchor`);
299
- const anchorAndShadows = anchors
300
- .map((anchor) => ({
301
- anchor,
302
- anchorShadow: anchorShapes.find((shape) => shape.attrs.adjustType === anchor.adjustType && shape.attrs.manualIndex === anchor.manualIndex) as Konva.Circle
303
- }))
304
- .filter((o) => o.anchorShadow !== void 0);
305
- return Line.createAnchorShapes(render, graph, anchorAndShadows, adjustAnchor);
306
- }
307
-
308
- /**
309
- * 默认图形大小
310
- */
311
- static size = 100;
312
-
313
- /**
314
- * 直线、折线 对应的 Konva 实例
315
- */
316
- private line: Konva.Line;
317
-
318
- constructor(render: Render, dropPoint: Konva.Vector2d) {
319
- super(render, dropPoint, {
320
- type: "Line",
321
- anchors: [{ adjustType: 'start' }, { adjustType: 'end' }].map((o) => ({ adjustType: o.adjustType })),
322
- linkAnchors: [
323
- { x: 0, y: 0, alias: 'start' },
324
- { x: 0, y: 0, alias: 'end' }
325
- ] as AssetInfoPoint[]
326
- });
327
- this.line = new Konva.Arrow({
328
- name: 'graph',
329
- x: 0,
330
- y: 0,
331
- stroke: "#000000",
332
- strokeWidth: 1,
333
- fill: "#000000",
334
- points: [],
335
- pointerAtBeginning: false,
336
- pointerAtEnding: false
337
- });
338
- // 给予 1 像素,防止导出图片 toDataURL 失败
339
- this.group.size({ width: 1, height: 1 });
340
- this.group.add(this.line);
341
- this.group.position(this.dropPoint);
342
- }
343
-
344
- // 实现:拖动进行时
345
- override drawMove(point: Konva.Vector2d): void {
346
- const offsetX = point.x - this.dropPoint.x,
347
- offsetY = point.y - this.dropPoint.y;
348
- const linkPoints = [ // 起点、终点
349
- [this.line.x(), this.line.y()],
350
- [this.line.x() + offsetX, this.line.y() + offsetY]
351
- ];
352
- // 直线、折线 路径
353
- this.line.points(linkPoints.flat());
354
- // 更新 图形 的 调整点 的 锚点位置
355
- Line.updateAnchorShadows(this.group, this.anchorShadows, this.line);
356
- // 更新 图形 的 连接点 的 锚点位置
357
- Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line);
358
- this.render.redraw([GraphDraw.NAME, LinkDraw.NAME, PreviewDraw.NAME]);
359
- }
360
-
361
- // 实现:拖动结束
362
- override drawEnd(): void {
363
- if (this.line.width() <= 10 && this.line.height() <= 10) {
364
- const width = Line.size, height = width;
365
- const linkPoints = [
366
- [this.line.x(), this.line.y()],
367
- [this.line.x() + width, this.line.y() + height]
368
- ];
369
- this.line.points(linkPoints.flat());
370
- }
371
- Line.updateAnchor(this.render, this.group);
372
- Line.updateAnchorShadows(this.group, this.anchorShadows, this.line);
373
- Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line);
374
- const size = {
375
- width: this.line.size().width - 10,
376
- height: this.line.size().height - 10
377
- };
378
- this.group.size(size);
379
- this.render.attractTool.alignLinesClear();
380
- this.render.updateHistory();
381
- this.render.redraw([GraphDraw.NAME, LinkDraw.NAME, PreviewDraw.NAME]);
382
- super.drawEnd(size, {
383
- x: Math.min(...this.line.points().reduce((arr, item, idx) => {
384
- if (idx % 2 === 0) arr.push(item);
385
- return arr;
386
- }, [] as number[])),
387
- y: Math.min(...this.line.points().reduce((arr, item, idx) => {
388
- if (idx % 2 === 1) arr.push(item);
389
- return arr;
390
- }, [] as number[]))
391
- });
392
- }
393
-
394
- /**
395
- * 更新 调整点(拐点)
396
- * @param render
397
- * @param graph
398
- */
399
- static updateAnchor(render: Render, graph: Konva.Group) {
400
- const anchors = graph.attrs.anchors ?? [];
401
- const anchorShadows = graph.find('.anchor') ?? [];
402
- const shape = graph.findOne('.graph') as Konva.Line;
403
- if (shape) {
404
- let manualPoints = (shape.attrs.manualPoints ?? []) as LineManualPoint[];
405
- const points = shape.points();
406
- const linkPoints = [
407
- [points[0], points[1]],
408
- ...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),
409
- [points[points.length - 2], points[points.length - 1]]
410
- ];
411
- // 清空 调整点(拐点),保留 start end
412
- anchors.splice(2);
413
- const shadows = anchorShadows.splice(2);
414
- for (const shadow of shadows) {
415
- shadow.remove();
416
- shadow.destroy();
417
- }
418
- manualPoints = [];
419
- for (let i = linkPoints.length - 1; i > 0; i--) {
420
- linkPoints.splice(i, 0, []);
421
- }
422
- for (let i = 1; i < linkPoints.length - 1; i++) {
423
- const anchor = {
424
- type: graph.attrs.graphType,
425
- adjustType: 'manual',
426
- name: 'anchor',
427
- groupId: graph.id(),
428
- manualIndex: i,
429
- adjusted: false
430
- };
431
- if (linkPoints[i].length === 0) {
432
- anchor.adjusted = false;
433
- const prev = linkPoints[i - 1];
434
- const next = linkPoints[i + 1];
435
- const circle = new Konva.Circle({
436
- adjustType: anchor.adjustType,
437
- anchorType: anchor.type,
438
- name: anchor.name,
439
- manualIndex: anchor.manualIndex,
440
- radius: 0,
441
- x: (prev[0] + next[0]) / 2,
442
- y: (prev[1] + next[1]) / 2,
443
- anchor
444
- });
445
- graph.add(circle);
446
- } else {
447
- anchor.adjusted = true;
448
- const circle = new Konva.Circle({
449
- adjustType: anchor.adjustType,
450
- anchorType: anchor.type,
451
- name: anchor.name,
452
- manualIndex: anchor.manualIndex,
453
- adjusted: true,
454
- radius: 0,
455
- x: linkPoints[i][0],
456
- y: linkPoints[i][1],
457
- anchor
458
- });
459
- graph.add(circle);
460
- manualPoints.push({ x: linkPoints[i][0], y: linkPoints[i][1], index: anchor.manualIndex });
461
- }
462
- anchors.push(anchor);
463
- }
464
- shape.setAttr('manualPoints', manualPoints);
465
- graph.setAttr('anchors', anchors);
466
- }
467
- }
468
-
469
- /**
470
- * 调整之前
471
- */
472
- static adjustStart(
473
- render: Render,
474
- graph: Konva.Group,
475
- adjustAnchor: GraphAnchor & { manualIndex?: number; adjusted?: boolean },
476
- endPoint: Konva.Vector2d
477
- ) {
478
- const { x: gx, y: gy } = graph.position();
479
- const shape = graph.findOne('.graph') as Konva.Line;
480
- if (shape && typeof adjustAnchor.manualIndex === 'number') {
481
- const manualPoints = (shape.attrs.manualPoints ?? []) as LineManualPoint[];
482
- if (adjustAnchor.adjusted) {
483
- } else {
484
- manualPoints.push({
485
- x: endPoint.x - gx,
486
- y: endPoint.y - gy,
487
- index: adjustAnchor.manualIndex
488
- });
489
- shape.setAttr('manualPoints', manualPoints);
490
- }
491
- Line.updateAnchor(render, graph);
492
- }
493
- }
1
+ import Konva from 'konva';
2
+ import { GraphAnchor, Render, AssetInfoPoint, LineManualPoint } from '../types';
3
+ import { GraphDraw, LinkDraw, PreviewDraw } from '../draws';
4
+ import { BaseGraph } from './base-graph';
5
+
6
+ /**
7
+ * 直线、折线
8
+ */
9
+ export class Line extends BaseGraph {
10
+ // 实现:更新 图形 的 调整点 的 锚点位置
11
+ static override updateAnchorShadows(graph: Konva.Group, anchorShadows: Konva.Circle[], shape?: Konva.Line): void {
12
+ if (shape) {
13
+ const points = shape.points();
14
+ for (const shadow of anchorShadows) {
15
+ switch (shadow.attrs.adjustType) {
16
+ case 'start':
17
+ shadow.position({ x: points[0], y: points[1] });
18
+ break;
19
+ case 'end':
20
+ shadow.position({ x: points[points.length - 2], y: points[points.length - 1] });
21
+ break;
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ // 实现:更新 图形 的 连接点 的 锚点位置
28
+ static override updateLinkAnchorShadows(graph: Konva.Group, linkAnchorShadows: Konva.Circle[], shape?: Konva.Line): void {
29
+ if (shape) {
30
+ const points = shape.points();
31
+ for (const shadow of linkAnchorShadows) {
32
+ switch (shadow.attrs.alias) {
33
+ case 'start':
34
+ shadow.position({ x: points[0], y: points[1] });
35
+ break;
36
+ case 'end':
37
+ shadow.position({ x: points[points.length - 2], y: points[points.length - 1] });
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ static calculateAngle(sideA: number, sideB: number) {
45
+ if (!isNaN(sideA) && !isNaN(sideB)) {
46
+ const angleInRadians = Math.atan2(sideA, sideB);
47
+ const angleInDegrees = angleInRadians * (180 / Math.PI);
48
+ return angleInDegrees;
49
+ }
50
+ return 0;
51
+ }
52
+
53
+ // 实现:生成 调整点
54
+ static override createAnchorShapes(
55
+ render: Render,
56
+ graph: Konva.Group,
57
+ anchorAndShadows: {
58
+ anchor: GraphAnchor;
59
+ anchorShadow: Konva.Circle;
60
+ shape?: Konva.Shape;
61
+ }[],
62
+ // eslint-disable-next-line
63
+ adjustAnchor?: GraphAnchor
64
+ ): {
65
+ anchorAndShadows: {
66
+ anchor: GraphAnchor;
67
+ anchorShadow: Konva.Circle;
68
+ shape?: Konva.Shape | undefined;
69
+ }[]
70
+ } {
71
+ const stageState = render.getStageState();
72
+ const graphShape = graph.findOne('.graph') as Konva.Line;
73
+ if (graphShape) {
74
+ const points = graphShape.points();
75
+ for (const anchorAndShadow of anchorAndShadows) {
76
+ let rotate = 0;
77
+ const { anchor, anchorShadow } = anchorAndShadow;
78
+ const x = render.toStageValue(anchorShadow.getAbsolutePosition().x - stageState.x),
79
+ y = render.toStageValue(anchorShadow.getAbsolutePosition().y - stageState.y);
80
+ if (anchor.adjustType === 'manual') {
81
+ const anchorShape = new Konva.Circle({
82
+ name: 'anchor',
83
+ anchor: anchor,
84
+ fill: anchor.adjusted ? `rgba(0,0,0,0.4)` : `rgba(0,0,255,0.4)`,
85
+ radius: render.toStageValue(5),
86
+ strokeWidth: 0,
87
+ x: x,
88
+ y: y,
89
+ rotation: graph.getAbsoluteRotation(),
90
+ visible: graph.attrs.adjusting || graph.attrs.hover === true
91
+ });
92
+ anchorShape.on('mouseenter', () => {
93
+ document.body.style.cursor = 'move';
94
+ graph.setAttr('hover', true);
95
+ graph.setAttr('hoverAnchor', true);
96
+ });
97
+ anchorShape.on('mouseleave', () => {
98
+ document.body.style.cursor = anchorShape.attrs.adjusting ? 'move' : 'default';
99
+ graph.setAttr('hover', false);
100
+ graph.setAttr('hoverAnchor', false);
101
+ render.redraw([GraphDraw.NAME]);
102
+ });
103
+ anchorAndShadow.shape = anchorShape;
104
+ } else {
105
+ if (anchor.adjustType === 'start') {
106
+ rotate = Line.calculateAngle(points[2] - points[0], points[3] - points[1]);
107
+ } else if (anchor.adjustType === 'end') {
108
+ rotate = Line.calculateAngle(points[points.length - 2] - points[points.length - 4], points[points.length - 1] - points[points.length - 3]);
109
+ }
110
+ const cos = Math.cos((rotate * Math.PI) / 180);
111
+ const sin = Math.sin((rotate * Math.PI) / 180);
112
+ const offset = render.toStageValue(render.pointSize - 20);
113
+ const offsetX = offset * sin;
114
+ const offsetY = offset * cos;
115
+ const anchorShape = new Konva.Circle({
116
+ name: 'anchor',
117
+ anchor: anchor,
118
+ fill: `rgba(0,0,255,0.4)`,
119
+ radius: render.toStageValue(5),
120
+ strokeWidth: 0,
121
+ x: x,
122
+ y: y,
123
+ offsetX: anchor.adjustType === 'start' ? offsetX : anchor.adjustType === 'end' ? -offsetX : 0,
124
+ offsetY: anchor.adjustType === 'start' ? offsetY : anchor.adjustType === 'end' ? -offsetY : 0,
125
+ rotation: graph.getAbsoluteRotation(),
126
+ visible: graph.attrs.adjusting || graph.attrs.hover === true
127
+ });
128
+ anchorShape.on('mouseenter', () => {
129
+ document.body.style.cursor = 'move';
130
+ graph.setAttr('hover', true);
131
+ graph.setAttr('hoverAnchor', true);
132
+ });
133
+ anchorShape.on('mouseleave', () => {
134
+ document.body.style.cursor = anchorShape.attrs.adjusting ? 'move' : 'default';
135
+ graph.setAttr('hover', false);
136
+ graph.setAttr('hoverAnchor', false);
137
+ render.redraw([GraphDraw.NAME]);
138
+ });
139
+ anchorAndShadow.shape = anchorShape;
140
+ }
141
+ }
142
+ }
143
+ return { anchorAndShadows };
144
+ }
145
+
146
+ /**
147
+ * 矩阵变换:坐标系中的一个点,围绕着另外一个点进行旋转
148
+ * - - - - - - - -
149
+ * |x`| |cos -sin| |x-a| |a|
150
+ * | | = | | | | +
151
+ * |y`| |sin cos| |y-b| |b|
152
+ * - - - - - - - -
153
+ * @param x 目标节点坐标 x
154
+ * @param y 目标节点坐标 y
155
+ * @param centerX 围绕的点坐标 x
156
+ * @param centerY 围绕的点坐标 y
157
+ * @param angle 旋转角度
158
+ * @returns
159
+ */
160
+ static rotatePoint(x: number, y: number, centerX: number, centerY: number, angle: number) {
161
+ const radians = (angle * Math.PI) / 180;
162
+ const newX = Math.cos(radians) * (x - centerX) - Math.sin(radians) * (y - centerY) + centerX;
163
+ const newY = Math.sin(radians) * (x - centerX) + Math.cos(radians) * (y - centerY) + centerY;
164
+ return { x: newX, y: newY };
165
+ }
166
+
167
+ // 实现:调整 图形
168
+ static override adjust(
169
+ render: Render,
170
+ graph: Konva.Group,
171
+ graphSnap: Konva.Group,
172
+ adjustShape: Konva.Shape,
173
+ anchorAndShadows: {
174
+ anchor: GraphAnchor;
175
+ anchorShadow: Konva.Circle;
176
+ shape?: Konva.Shape | undefined;
177
+ }[],
178
+ startPoint: Konva.Vector2d,
179
+ endPoint: Konva.Vector2d,
180
+ hoverRect?: Konva.Rect
181
+ ) {
182
+ // 目标 直线、折线
183
+ const line = graph.findOne('.graph') as Konva.Line;
184
+ const lineSnap = graphSnap.findOne('.graph') as Konva.Line;
185
+ const anchors = (graph.find('.anchor') ?? []) as Konva.Circle[];
186
+ const anchorsSnap = (graphSnap.find('.anchor') ?? []) as Konva.Circle[];
187
+ const linkAnchors = (graph.find('.link-anchor') ?? []) as Konva.Circle[];
188
+ if (line && lineSnap) {
189
+ const stageState = render.getStageState();
190
+ {
191
+ const [graphRotation, adjustType, ex, ey] = [
192
+ Math.round(graph.rotation()),
193
+ adjustShape.attrs.anchor?.adjustType,
194
+ endPoint.x,
195
+ endPoint.y
196
+ ];
197
+ const { x: cx, y: cy, width: cw, height: ch } = graphSnap.getClientRect();
198
+ const { x, y } = graph.position();
199
+ const [centerX, centerY] = [cx + cw / 2, cy + ch / 2];
200
+ const { x: sx, y: sy } = Line.rotatePoint(ex, ey, centerX, centerY, -graphRotation);
201
+ const { x: rx, y: ry } = Line.rotatePoint(x, y, centerX, centerY, -graphRotation);
202
+ const points = line.points();
203
+ const manualPoints = (line.attrs.manualPoints ?? []) as LineManualPoint[];
204
+ if (adjustType === 'manual') {
205
+ if (adjustShape.attrs.anchor?.manualIndex !== void 0) {
206
+ const index = adjustShape.attrs.anchor?.adjusted ? adjustShape.attrs.anchor?.manualIndex : adjustShape.attrs.anchor?.manualIndex + 1;
207
+ const manualPointIndex = manualPoints.findIndex((o) => o.index === index);
208
+ if (manualPointIndex > -1) {
209
+ manualPoints[manualPointIndex].x = (sx - rx) / graph.scaleX();
210
+ manualPoints[manualPointIndex].y = (sy - ry) / graph.scaleY();
211
+ }
212
+ const linkPoints = [
213
+ [points[0], points[1]],
214
+ ...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),
215
+ [points[points.length - 2], points[points.length - 1]]
216
+ ];
217
+ line.setAttr('manualPoints', manualPoints);
218
+ line.points(linkPoints.flat());
219
+ const adjustAnchorShadow = anchors.find((o) => o.attrs.adjustType === 'manual' && o.attrs.manualIndex === index);
220
+ if (adjustAnchorShadow) {
221
+ adjustAnchorShadow.position({
222
+ x: (sx - rx) / graph.scaleX(),
223
+ y: (sy - ry) / graph.scaleY()
224
+ });
225
+ }
226
+ }
227
+ } else {
228
+ const anchor = anchors.find((o) => o.attrs.adjustType === adjustType);
229
+ const anchorShadow = anchorsSnap.find((o) => o.attrs.adjustType === adjustType);
230
+ if (anchor && anchorShadow) {
231
+ const linkPoints = [
232
+ [points[0], points[1]],
233
+ ...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),
234
+ [points[points.length - 2], points[points.length - 1]]
235
+ ];
236
+ switch (adjustType) {
237
+ case 'start':
238
+ linkPoints[0] = [(sx - rx) / graph.scaleX(), (sy - ry) / graph.scaleY()];
239
+ line.points(linkPoints.flat());
240
+ break;
241
+ case 'end':
242
+ linkPoints[linkPoints.length - 1] = [(sx - rx) / graph.scaleX(), (sy - ry) / graph.scaleY()];
243
+ line.points(linkPoints.flat());
244
+ break;
245
+ }
246
+ }
247
+ }
248
+ }
249
+ Line.updateAnchor(render, graph); // 更新 调整点(拐点)
250
+ Line.updateAnchorShadows(graph, anchors, line); // 更新 调整点 的 锚点 位置
251
+ Line.updateLinkAnchorShadows(graph, linkAnchors, line); // 更新 图形 的 连接点 的 锚点位置
252
+ for (const anchor of anchors) {
253
+ for (const { shape } of anchorAndShadows) {
254
+ if (shape) {
255
+ if (shape.attrs.anchor?.adjustType === anchor.attrs.adjustType) {
256
+ const anchorShadow = graph.find(`.anchor`).find((o) => o.attrs.adjustType === anchor.attrs.adjustType);
257
+ if (anchorShadow) {
258
+ shape.position({
259
+ x: render.toStageValue(anchorShadow.getAbsolutePosition().x - stageState.x),
260
+ y: render.toStageValue(anchorShadow.getAbsolutePosition().y - stageState.y)
261
+ });
262
+ shape.rotation(graph.getAbsoluteRotation());
263
+ }
264
+ }
265
+ }
266
+ }
267
+ }
268
+ render.redraw([GraphDraw.NAME, LinkDraw.NAME, PreviewDraw.NAME]);
269
+ }
270
+ BaseGraph.adjust(
271
+ render,
272
+ graph,
273
+ graphSnap,
274
+ adjustShape,
275
+ anchorAndShadows,
276
+ startPoint,
277
+ endPoint,
278
+ hoverRect,
279
+ line.size(),
280
+ {
281
+ x: Math.min(...line.points().reduce((arr, item, idx) => {
282
+ if (idx % 2 === 0) arr.push(item);
283
+ return arr;
284
+ }, [] as number[])),
285
+ y: Math.min(...line.points().reduce((arr, item, idx) => {
286
+ if (idx % 2 === 1) arr.push(item);
287
+ return arr;
288
+ }, [] as number[]))
289
+ }
290
+ );
291
+ }
292
+
293
+ /**
294
+ * 提供给 GraphDraw draw 使用
295
+ */
296
+ static override draw(graph: Konva.Group, render: Render, adjustAnchor?: GraphAnchor) {
297
+ const anchors = (graph.attrs.anchors ?? []) as (GraphAnchor & { manualIndex?: number; adjusted?: boolean })[];
298
+ const anchorShapes = graph.find(`.anchor`);
299
+ const anchorAndShadows = anchors
300
+ .map((anchor) => ({
301
+ anchor,
302
+ anchorShadow: anchorShapes.find((shape) => shape.attrs.adjustType === anchor.adjustType && shape.attrs.manualIndex === anchor.manualIndex) as Konva.Circle
303
+ }))
304
+ .filter((o) => o.anchorShadow !== void 0);
305
+ return Line.createAnchorShapes(render, graph, anchorAndShadows, adjustAnchor);
306
+ }
307
+
308
+ /**
309
+ * 默认图形大小
310
+ */
311
+ static size = 100;
312
+
313
+ /**
314
+ * 直线、折线 对应的 Konva 实例
315
+ */
316
+ private line: Konva.Line;
317
+
318
+ constructor(render: Render, dropPoint: Konva.Vector2d) {
319
+ super(render, dropPoint, {
320
+ type: "Line",
321
+ anchors: [{ adjustType: 'start' }, { adjustType: 'end' }].map((o) => ({ adjustType: o.adjustType })),
322
+ linkAnchors: [
323
+ { x: 0, y: 0, alias: 'start' },
324
+ { x: 0, y: 0, alias: 'end' }
325
+ ] as AssetInfoPoint[]
326
+ });
327
+ this.line = new Konva.Arrow({
328
+ name: 'graph',
329
+ x: 0,
330
+ y: 0,
331
+ stroke: "#000000",
332
+ strokeWidth: 1,
333
+ fill: "#000000",
334
+ points: [],
335
+ pointerAtBeginning: false,
336
+ pointerAtEnding: false
337
+ });
338
+ // 给予 1 像素,防止导出图片 toDataURL 失败
339
+ this.group.size({ width: 1, height: 1 });
340
+ this.group.add(this.line);
341
+ this.group.position(this.dropPoint);
342
+ }
343
+
344
+ // 实现:拖动进行时
345
+ override drawMove(point: Konva.Vector2d): void {
346
+ const offsetX = point.x - this.dropPoint.x,
347
+ offsetY = point.y - this.dropPoint.y;
348
+ const linkPoints = [ // 起点、终点
349
+ [this.line.x(), this.line.y()],
350
+ [this.line.x() + offsetX, this.line.y() + offsetY]
351
+ ];
352
+ // 直线、折线 路径
353
+ this.line.points(linkPoints.flat());
354
+ // 更新 图形 的 调整点 的 锚点位置
355
+ Line.updateAnchorShadows(this.group, this.anchorShadows, this.line);
356
+ // 更新 图形 的 连接点 的 锚点位置
357
+ Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line);
358
+ this.render.redraw([GraphDraw.NAME, LinkDraw.NAME, PreviewDraw.NAME]);
359
+ }
360
+
361
+ // 实现:拖动结束
362
+ override drawEnd(): void {
363
+ if (this.line.width() <= 10 && this.line.height() <= 10) {
364
+ const width = Line.size, height = width;
365
+ const linkPoints = [
366
+ [this.line.x(), this.line.y()],
367
+ [this.line.x() + width, this.line.y() + height]
368
+ ];
369
+ this.line.points(linkPoints.flat());
370
+ }
371
+ Line.updateAnchor(this.render, this.group);
372
+ Line.updateAnchorShadows(this.group, this.anchorShadows, this.line);
373
+ Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line);
374
+ const size = {
375
+ width: this.line.size().width - 10,
376
+ height: this.line.size().height - 10
377
+ };
378
+ this.group.size(size);
379
+ this.render.attractTool.alignLinesClear();
380
+ this.render.updateHistory();
381
+ this.render.redraw([GraphDraw.NAME, LinkDraw.NAME, PreviewDraw.NAME]);
382
+ super.drawEnd(size, {
383
+ x: Math.min(...this.line.points().reduce((arr, item, idx) => {
384
+ if (idx % 2 === 0) arr.push(item);
385
+ return arr;
386
+ }, [] as number[])),
387
+ y: Math.min(...this.line.points().reduce((arr, item, idx) => {
388
+ if (idx % 2 === 1) arr.push(item);
389
+ return arr;
390
+ }, [] as number[]))
391
+ });
392
+ }
393
+
394
+ /**
395
+ * 更新 调整点(拐点)
396
+ * @param render
397
+ * @param graph
398
+ */
399
+ static updateAnchor(render: Render, graph: Konva.Group) {
400
+ const anchors = graph.attrs.anchors ?? [];
401
+ const anchorShadows = graph.find('.anchor') ?? [];
402
+ const shape = graph.findOne('.graph') as Konva.Line;
403
+ if (shape) {
404
+ let manualPoints = (shape.attrs.manualPoints ?? []) as LineManualPoint[];
405
+ const points = shape.points();
406
+ const linkPoints = [
407
+ [points[0], points[1]],
408
+ ...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),
409
+ [points[points.length - 2], points[points.length - 1]]
410
+ ];
411
+ // 清空 调整点(拐点),保留 start end
412
+ anchors.splice(2);
413
+ const shadows = anchorShadows.splice(2);
414
+ for (const shadow of shadows) {
415
+ shadow.remove();
416
+ shadow.destroy();
417
+ }
418
+ manualPoints = [];
419
+ for (let i = linkPoints.length - 1; i > 0; i--) {
420
+ linkPoints.splice(i, 0, []);
421
+ }
422
+ for (let i = 1; i < linkPoints.length - 1; i++) {
423
+ const anchor = {
424
+ type: graph.attrs.graphType,
425
+ adjustType: 'manual',
426
+ name: 'anchor',
427
+ groupId: graph.id(),
428
+ manualIndex: i,
429
+ adjusted: false
430
+ };
431
+ if (linkPoints[i].length === 0) {
432
+ anchor.adjusted = false;
433
+ const prev = linkPoints[i - 1];
434
+ const next = linkPoints[i + 1];
435
+ const circle = new Konva.Circle({
436
+ adjustType: anchor.adjustType,
437
+ anchorType: anchor.type,
438
+ name: anchor.name,
439
+ manualIndex: anchor.manualIndex,
440
+ radius: 0,
441
+ x: (prev[0] + next[0]) / 2,
442
+ y: (prev[1] + next[1]) / 2,
443
+ anchor
444
+ });
445
+ graph.add(circle);
446
+ } else {
447
+ anchor.adjusted = true;
448
+ const circle = new Konva.Circle({
449
+ adjustType: anchor.adjustType,
450
+ anchorType: anchor.type,
451
+ name: anchor.name,
452
+ manualIndex: anchor.manualIndex,
453
+ adjusted: true,
454
+ radius: 0,
455
+ x: linkPoints[i][0],
456
+ y: linkPoints[i][1],
457
+ anchor
458
+ });
459
+ graph.add(circle);
460
+ manualPoints.push({ x: linkPoints[i][0], y: linkPoints[i][1], index: anchor.manualIndex });
461
+ }
462
+ anchors.push(anchor);
463
+ }
464
+ shape.setAttr('manualPoints', manualPoints);
465
+ graph.setAttr('anchors', anchors);
466
+ }
467
+ }
468
+
469
+ /**
470
+ * 调整之前
471
+ */
472
+ static adjustStart(
473
+ render: Render,
474
+ graph: Konva.Group,
475
+ adjustAnchor: GraphAnchor & { manualIndex?: number; adjusted?: boolean },
476
+ endPoint: Konva.Vector2d
477
+ ) {
478
+ const { x: gx, y: gy } = graph.position();
479
+ const shape = graph.findOne('.graph') as Konva.Line;
480
+ if (shape && typeof adjustAnchor.manualIndex === 'number') {
481
+ const manualPoints = (shape.attrs.manualPoints ?? []) as LineManualPoint[];
482
+ if (adjustAnchor.adjusted) {
483
+ } else {
484
+ manualPoints.push({
485
+ x: endPoint.x - gx,
486
+ y: endPoint.y - gy,
487
+ index: adjustAnchor.manualIndex
488
+ });
489
+ shape.setAttr('manualPoints', manualPoints);
490
+ }
491
+ Line.updateAnchor(render, graph);
492
+ }
493
+ }
494
494
  }