aldehyde 0.2.516 → 0.2.518

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