aldehyde 0.2.473 → 0.2.474

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 (113) hide show
  1. package/lib/controls/entry-control.js +2 -2
  2. package/lib/controls/entry-control.js.map +1 -1
  3. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +47 -3
  4. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js +12 -12
  5. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js.map +1 -1
  6. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +77 -0
  7. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.ttf +0 -0
  8. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff +0 -0
  9. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff2 +0 -0
  10. package/lib/draw-canvas/edit/components/asset-bar/index.d.ts +5 -0
  11. package/lib/draw-canvas/edit/components/asset-bar/index.d.ts.map +1 -0
  12. package/lib/draw-canvas/edit/components/asset-bar/index.js +78 -0
  13. package/lib/draw-canvas/edit/components/asset-bar/index.js.map +1 -0
  14. package/lib/draw-canvas/edit/components/asset-bar/index.less +36 -0
  15. package/lib/draw-canvas/edit/components/main-header/index.d.ts +14 -0
  16. package/lib/draw-canvas/edit/components/main-header/index.d.ts.map +1 -0
  17. package/lib/draw-canvas/edit/components/main-header/index.js +163 -0
  18. package/lib/draw-canvas/edit/components/main-header/index.js.map +1 -0
  19. package/lib/draw-canvas/edit/components/main-header/index.less +21 -0
  20. package/lib/draw-canvas/edit/components/render/index.d.ts +86 -0
  21. package/lib/draw-canvas/edit/components/render/index.d.ts.map +1 -0
  22. package/lib/draw-canvas/edit/components/render/index.js +686 -0
  23. package/lib/draw-canvas/edit/components/render/index.js.map +1 -0
  24. package/lib/draw-canvas/edit/components/render/types.d.ts +243 -0
  25. package/lib/draw-canvas/edit/components/render/types.d.ts.map +1 -0
  26. package/lib/draw-canvas/edit/components/render/types.js +66 -0
  27. package/lib/draw-canvas/edit/components/render/types.js.map +1 -0
  28. package/lib/draw-canvas/edit/components/setting-form/index.d.ts +19 -0
  29. package/lib/draw-canvas/edit/components/setting-form/index.d.ts.map +1 -0
  30. package/lib/draw-canvas/edit/components/setting-form/index.js +164 -0
  31. package/lib/draw-canvas/edit/components/setting-form/index.js.map +1 -0
  32. package/lib/draw-canvas/edit/index.d.ts +5 -0
  33. package/lib/draw-canvas/edit/index.d.ts.map +1 -0
  34. package/lib/draw-canvas/edit/index.js +112 -0
  35. package/lib/draw-canvas/edit/index.js.map +1 -0
  36. package/lib/draw-canvas/edit/index.less +34 -0
  37. package/lib/form/form-Item-group.d.ts.map +1 -1
  38. package/lib/form/form-Item-group.js +1 -1
  39. package/lib/form/form-Item-group.js.map +1 -1
  40. package/lib/icon/local-aliIcon/iconfont.js +5 -5
  41. package/lib/icon/local-aliIcon/iconfont.js.map +1 -1
  42. package/lib/table/relation-table.d.ts +4 -0
  43. package/lib/table/relation-table.d.ts.map +1 -1
  44. package/lib/tmpl/hcservice-v3.d.ts +1 -0
  45. package/lib/tmpl/hcservice-v3.d.ts.map +1 -1
  46. package/lib/tmpl/hcservice-v3.js +27 -0
  47. package/lib/tmpl/hcservice-v3.js.map +1 -1
  48. package/lib/tmpl/interface.d.ts +4 -0
  49. package/lib/tmpl/interface.d.ts.map +1 -1
  50. package/lib/tmpl/interface.js.map +1 -1
  51. package/lib/units/index.d.ts +1 -0
  52. package/lib/units/index.d.ts.map +1 -1
  53. package/lib/units/index.js +16 -0
  54. package/lib/units/index.js.map +1 -1
  55. package/package.json +1 -1
  56. package/src/aldehyde/controls/entry-control.tsx +2 -2
  57. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +47 -3
  58. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js +1 -1
  59. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +77 -0
  60. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.ttf +0 -0
  61. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff +0 -0
  62. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff2 +0 -0
  63. package/src/aldehyde/draw-canvas/edit/components/asset-bar/index.less +36 -0
  64. package/src/aldehyde/draw-canvas/edit/components/asset-bar/index.tsx +93 -0
  65. package/src/aldehyde/draw-canvas/edit/components/main-header/index.less +21 -0
  66. package/src/aldehyde/draw-canvas/edit/components/main-header/index.tsx +187 -0
  67. package/src/aldehyde/draw-canvas/edit/components/render/draws/bg-draw.ts +98 -0
  68. package/src/aldehyde/draw-canvas/edit/components/render/draws/contextmenu-draw.ts +307 -0
  69. package/src/aldehyde/draw-canvas/edit/components/render/draws/graph-draw.ts +251 -0
  70. package/src/aldehyde/draw-canvas/edit/components/render/draws/index.ts +7 -0
  71. package/src/aldehyde/draw-canvas/edit/components/render/draws/link-draw.ts +1416 -0
  72. package/src/aldehyde/draw-canvas/edit/components/render/draws/preview-draw.ts +257 -0
  73. package/src/aldehyde/draw-canvas/edit/components/render/draws/ref-line-draw.ts +72 -0
  74. package/src/aldehyde/draw-canvas/edit/components/render/draws/ruler-draw.ts +167 -0
  75. package/src/aldehyde/draw-canvas/edit/components/render/graphs/base-graph.ts +241 -0
  76. package/src/aldehyde/draw-canvas/edit/components/render/graphs/bezier.ts +542 -0
  77. package/src/aldehyde/draw-canvas/edit/components/render/graphs/circle.ts +700 -0
  78. package/src/aldehyde/draw-canvas/edit/components/render/graphs/curve.ts +501 -0
  79. package/src/aldehyde/draw-canvas/edit/components/render/graphs/index.ts +6 -0
  80. package/src/aldehyde/draw-canvas/edit/components/render/graphs/line.ts +494 -0
  81. package/src/aldehyde/draw-canvas/edit/components/render/graphs/rect.ts +681 -0
  82. package/src/aldehyde/draw-canvas/edit/components/render/handlers/drag-handlers.ts +69 -0
  83. package/src/aldehyde/draw-canvas/edit/components/render/handlers/drag-outside-handlers.ts +162 -0
  84. package/src/aldehyde/draw-canvas/edit/components/render/handlers/graph-handlers.ts +108 -0
  85. package/src/aldehyde/draw-canvas/edit/components/render/handlers/index.ts +9 -0
  86. package/src/aldehyde/draw-canvas/edit/components/render/handlers/key-move-handlers.ts +50 -0
  87. package/src/aldehyde/draw-canvas/edit/components/render/handlers/link-handlers.ts +46 -0
  88. package/src/aldehyde/draw-canvas/edit/components/render/handlers/selection-handlers.ts +385 -0
  89. package/src/aldehyde/draw-canvas/edit/components/render/handlers/shutcut-handlers.ts +46 -0
  90. package/src/aldehyde/draw-canvas/edit/components/render/handlers/text-handlers.ts +82 -0
  91. package/src/aldehyde/draw-canvas/edit/components/render/handlers/zoom-handlers.ts +60 -0
  92. package/src/aldehyde/draw-canvas/edit/components/render/index.ts +768 -0
  93. package/src/aldehyde/draw-canvas/edit/components/render/tools/align-tool.ts +91 -0
  94. package/src/aldehyde/draw-canvas/edit/components/render/tools/asset-tool.ts +142 -0
  95. package/src/aldehyde/draw-canvas/edit/components/render/tools/attract-tool.ts +440 -0
  96. package/src/aldehyde/draw-canvas/edit/components/render/tools/copy-tool.ts +269 -0
  97. package/src/aldehyde/draw-canvas/edit/components/render/tools/import-export-tool.ts +603 -0
  98. package/src/aldehyde/draw-canvas/edit/components/render/tools/index.ts +9 -0
  99. package/src/aldehyde/draw-canvas/edit/components/render/tools/link-tool.ts +225 -0
  100. package/src/aldehyde/draw-canvas/edit/components/render/tools/position-tool.ts +212 -0
  101. package/src/aldehyde/draw-canvas/edit/components/render/tools/selection-tool.ts +132 -0
  102. package/src/aldehyde/draw-canvas/edit/components/render/tools/z-index-tool.ts +227 -0
  103. package/src/aldehyde/draw-canvas/edit/components/render/types.ts +287 -0
  104. package/src/aldehyde/draw-canvas/edit/components/render/utils/a-star.ts +116 -0
  105. package/src/aldehyde/draw-canvas/edit/components/render/utils/bezier-scene-func.ts +73 -0
  106. package/src/aldehyde/draw-canvas/edit/components/setting-form/index.tsx +200 -0
  107. package/src/aldehyde/draw-canvas/edit/index.less +34 -0
  108. package/src/aldehyde/draw-canvas/edit/index.tsx +138 -0
  109. package/src/aldehyde/form/form-Item-group.tsx +1 -0
  110. package/src/aldehyde/icon/local-aliIcon/iconfont.js +1 -1
  111. package/src/aldehyde/tmpl/hcservice-v3.tsx +14 -0
  112. package/src/aldehyde/tmpl/interface.tsx +2 -0
  113. package/src/aldehyde/units/index.tsx +15 -0
@@ -0,0 +1,768 @@
1
+ import * as _ from 'lodash';
2
+ import Konva from 'konva';
3
+ import { GraphDraw, LinkDraw, RulerDraw, PreviewDraw, RefLineDraw, BgDraw, ContextmenuDraw } from './draws';
4
+ import { LinkDrawPoint, GraphType, AssetType, RenderConfig, Draw, Handler, RenderEvents, LinkDrawPair, PageSettings, AssetSettings, ImageType, LinkSettings } from './types';
5
+ import { DragHandlers, ZoomHandlers, DragOutsideHandlers, SelectionHandlers, KeyMoveHandlers, ShutcutHandlers, LinkHandlers, GraphHandlers, TextHandlers } from './handlers';
6
+ import { AssetTool, SelectionTool, CopyTool, PositionTool, ZIndexTool, ImportExportTool, AlignTool, LinkTool, AttractTool } from './tools';
7
+
8
+ // 简单的事件系统替代 mitt
9
+ class SimpleEventEmitter {
10
+ private listeners: Map<string, Set<Function>> = new Map();
11
+
12
+ on(event: string, handler: Function) {
13
+ if (!this.listeners.has(event)) {
14
+ this.listeners.set(event, new Set());
15
+ }
16
+ this.listeners.get(event)!.add(handler);
17
+ return () => this.off(event, handler);
18
+ }
19
+
20
+ off(event: string, handler: Function) {
21
+ this.listeners.get(event)?.delete(handler);
22
+ }
23
+
24
+ emit(event: string, ...args: any[]) {
25
+ this.listeners.get(event)?.forEach(handler => handler(...args));
26
+ }
27
+ }
28
+
29
+ // 渲染器
30
+ export class Render {
31
+ stage: Konva.Stage;
32
+ layer: Konva.Layer = new Konva.Layer({ id: 'main' }); // 主要层
33
+ layerFloor: Konva.Layer = new Konva.Layer(); // 辅助层 - 背景
34
+ layerCover: Konva.Layer = new Konva.Layer({ id: 'cover' }); // 辅助层 - 连接线、对齐线
35
+ config: RenderConfig; // 配置
36
+ draws: { [index: string]: (Draw & Handler) | undefined } = {}; // 附加工具
37
+ assetTool: AssetTool; // 素材工具
38
+ selectionTool: SelectionTool; // 选择工具
39
+ copyTool: CopyTool; // 复制工具
40
+ positionTool: PositionTool; // 定位工具
41
+ zIndexTool: ZIndexTool; // 层级工具
42
+ importExportTool: ImportExportTool; // 导入导出
43
+ alignTool: AlignTool; // 对齐工具
44
+ linkTool: LinkTool; // 连线工具
45
+ attractTool: AttractTool; // 磁贴工具
46
+ groupTransformer: Konva.Group = new Konva.Group(); // 多选器层
47
+
48
+ // 多选器
49
+ transformer: Konva.Transformer = new Konva.Transformer({
50
+ shouldOverdrawWholeArea: true,
51
+ borderDash: [4, 4],
52
+ padding: 1,
53
+ rotationSnaps: [0, 45, 90, 135, 180, 225, 270, 315, 360],
54
+ flipEnabled: false
55
+ });
56
+
57
+ // 选择框
58
+ selectRect: Konva.Rect = new Konva.Rect({
59
+ id: 'selectRect',
60
+ fill: 'rgba(0,0,255,0.1)',
61
+ visible: false
62
+ });
63
+
64
+ // 事件处理
65
+ handlers: { [index: string]: Handler } = {};
66
+
67
+ // 参数
68
+ bgSize = 20;
69
+ rulerSize = 0;
70
+ previewSize = 0.2; // 预览框大小(比例)
71
+ pointSize = 6;
72
+ history: string[] = [];
73
+ historyIndex = -1;
74
+ graphType: GraphType | undefined = undefined; // 画图类型
75
+ texting = false; // 添加文字中
76
+
77
+ // 事件发射器(替代 mitt)
78
+ private emitter = new SimpleEventEmitter();
79
+ on: <K extends keyof RenderEvents>(event: K, handler: (payload: RenderEvents[K]) => void) => (() => void);
80
+ off: <K extends keyof RenderEvents>(event: K, handler: (payload: RenderEvents[K]) => void) => void;
81
+ emit: <K extends keyof RenderEvents>(event: K, payload: RenderEvents[K]) => void;
82
+
83
+ constructor(stageEle: HTMLDivElement, config: RenderConfig) {
84
+ this.config = config;
85
+ // 绑定事件方法
86
+ this.on = this.emitter.on.bind(this.emitter) as any;
87
+ this.off = this.emitter.off.bind(this.emitter) as any;
88
+ this.emit = this.emitter.emit.bind(this.emitter) as any;
89
+ if (this.config.showRuler) {
90
+ this.rulerSize = 40;
91
+ }
92
+ this.stage = new Konva.Stage({
93
+ container: stageEle,
94
+ x: this.rulerSize,
95
+ y: this.rulerSize,
96
+ width: config.width,
97
+ height: config.height
98
+ });
99
+ // 辅助层 - 顶层
100
+ this.groupTransformer.add(this.transformer);
101
+ this.groupTransformer.add(this.selectRect);
102
+ this.layerCover.add(this.groupTransformer);
103
+ // 附加工具
104
+ if (!this.config.readonly && this.config.showBg) {
105
+ this.draws[BgDraw.name] = new BgDraw(this, this.layerFloor, {
106
+ size: this.bgSize
107
+ });
108
+ }
109
+
110
+ this.draws[LinkDraw.name] = new LinkDraw(this, this.layerCover, {
111
+ size: this.pointSize
112
+ });
113
+
114
+ if (!this.config.readonly && this.config.showRuler) {
115
+ this.draws[RulerDraw.name] = new RulerDraw(this, this.layerCover, {
116
+ size: this.rulerSize
117
+ });
118
+ }
119
+
120
+ if (!this.config.readonly && this.config.showRefLine) {
121
+ this.draws[RefLineDraw.name] = new RefLineDraw(this, this.layerCover, {
122
+ padding: this.rulerSize
123
+ });
124
+ }
125
+
126
+ if (this.config.showContextmenu) {
127
+ this.draws[ContextmenuDraw.name] = new ContextmenuDraw(this, this.layerCover, {});
128
+ }
129
+
130
+ if (!this.config.readonly && this.config.showPreview) {
131
+ this.draws[PreviewDraw.name] = new PreviewDraw(this, this.layerCover, {
132
+ size: this.previewSize
133
+ });
134
+ }
135
+
136
+ this.draws[GraphDraw.name] = new GraphDraw(this, this.layerCover, {});
137
+
138
+ this.assetTool = new AssetTool(this); // 素材工具
139
+ this.selectionTool = new SelectionTool(this); // 选择工具
140
+ this.copyTool = new CopyTool(this); // 复制工具
141
+ this.positionTool = new PositionTool(this); // 定位工具
142
+ this.zIndexTool = new ZIndexTool(this); // 定位工具
143
+ this.importExportTool = new ImportExportTool(this); // 导入导出
144
+ this.alignTool = new AlignTool(this); // 对齐工具
145
+ this.linkTool = new LinkTool(this); // 对齐工具
146
+ this.attractTool = new AttractTool(this); // 磁贴工具
147
+
148
+ // 事件处理
149
+ this.handlers[DragHandlers.name] = new DragHandlers(this);
150
+ this.handlers[ZoomHandlers.name] = new ZoomHandlers(this);
151
+
152
+ if (!this.config.readonly) {
153
+ this.handlers[DragOutsideHandlers.name] = new DragOutsideHandlers(this);
154
+ this.handlers[SelectionHandlers.name] = new SelectionHandlers(this);
155
+ this.handlers[KeyMoveHandlers.name] = new KeyMoveHandlers(this);
156
+ this.handlers[LinkHandlers.name] = new LinkHandlers(this);
157
+ this.handlers[GraphHandlers.name] = new GraphHandlers(this);
158
+ this.handlers[TextHandlers.name] = new TextHandlers(this);
159
+ }
160
+ if (!this.config.readonly && this.config.showRefLine) {
161
+ if (this.draws[RefLineDraw.name] !== void 0) {
162
+ this.handlers[RefLineDraw.name] = this.draws[RefLineDraw.name]!;
163
+ }
164
+ }
165
+ this.handlers[ShutcutHandlers.name] = new ShutcutHandlers(this);
166
+ // 初始化
167
+ this.init();
168
+ }
169
+
170
+ // 初始化
171
+ init() {
172
+ this.stage.add(this.layerFloor);
173
+ this.draws[BgDraw.name]?.init();
174
+ this.stage.add(this.layer);
175
+ this.stage.add(this.layerCover);
176
+ this.draws[LinkDraw.name]?.init();
177
+ this.draws[RulerDraw.name]?.init();
178
+ this.draws[RefLineDraw.name]?.init();
179
+ this.draws[ContextmenuDraw.name]?.init();
180
+ this.draws[PreviewDraw.name]?.init();
181
+ // 事件绑定
182
+ this.eventBind();
183
+ // 更新历史
184
+ this.updateHistory();
185
+ }
186
+
187
+ // 更新 stage 尺寸
188
+ resize(width: number, height: number) {
189
+ this.stage.setAttrs({
190
+ width: width,
191
+ height: height
192
+ });
193
+ // 重绘
194
+ this.redraw();
195
+ }
196
+
197
+ // 移除元素
198
+ remove(nodes: Konva.Node[]) {
199
+ for (const node of nodes) {
200
+ if (node instanceof Konva.Transformer) {
201
+ // 移除已选择的节点
202
+ this.remove(this.selectionTool.selectingNodes);
203
+ } else {
204
+ // 移除相关联系线信息
205
+ const groupId = node.id();
206
+ for (const rn of this.layer.getChildren()) {
207
+ if (rn.id() !== groupId && Array.isArray(rn.attrs.points)) {
208
+ for (const point of rn.attrs.points) {
209
+ if (Array.isArray(point.pairs)) {
210
+ // 移除拐点记录
211
+ if (rn.attrs.manualPointsMap) {
212
+ point.pairs
213
+ .filter(
214
+ (pair: LinkDrawPair) =>
215
+ pair.from.groupId === groupId || pair.to.groupId === groupId
216
+ )
217
+ .forEach((pair: LinkDrawPair) => {
218
+ rn.attrs.manualPointsMap[pair.id] = undefined;
219
+ });
220
+ }
221
+ // 连接线信息
222
+ point.pairs = point.pairs.filter(
223
+ (pair: LinkDrawPair) =>
224
+ pair.from.groupId !== groupId && pair.to.groupId !== groupId
225
+ );
226
+ }
227
+ }
228
+ rn.setAttrs({ points: rn.attrs.points });
229
+ }
230
+ }
231
+ // 移除未选择的节点
232
+ node.destroy();
233
+ }
234
+ }
235
+
236
+ if (nodes.length > 0) {
237
+ // 清除选择
238
+ this.selectionTool.selectingClear();
239
+ this.linkTool.selectingClear();
240
+ // 更新历史
241
+ this.updateHistory();
242
+ // 重绘
243
+ this.redraw();
244
+ }
245
+ }
246
+
247
+ // 撤销
248
+ prevHistory() {
249
+ const record = this.history[this.historyIndex - 1];
250
+ if (record) {
251
+ this.importExportTool.restore(record, true);
252
+ this.historyIndex--;
253
+ // 历史变化事件
254
+ this.emit('history-change', {
255
+ records: _.clone(this.history),
256
+ index: this.historyIndex
257
+ });
258
+ }
259
+ }
260
+
261
+ // 恢复
262
+ nextHistory() {
263
+ const record = this.history[this.historyIndex + 1];
264
+ if (record) {
265
+ this.importExportTool.restore(record, true);
266
+ this.historyIndex++;
267
+ // 历史变化事件
268
+ this.emit('history-change', {
269
+ records: _.clone(this.history),
270
+ index: this.historyIndex
271
+ });
272
+ }
273
+ }
274
+
275
+ updateHistory() {
276
+ this.history.splice(this.historyIndex + 1);
277
+ this.history.push(this.importExportTool.save());
278
+ this.historyIndex = this.history.length - 1;
279
+ // 历史变化事件
280
+ this.emit('history-change', {
281
+ records: _.clone(this.history),
282
+ index: this.historyIndex
283
+ });
284
+ }
285
+
286
+ // 事件绑定
287
+ eventBind() {
288
+ for (const event of [
289
+ 'mousedown',
290
+ 'mouseup',
291
+ 'mousemove',
292
+ 'wheel',
293
+ 'contextmenu',
294
+ 'pointerclick'
295
+ ]) {
296
+ this.stage.on(event, (e) => {
297
+ e?.evt?.preventDefault();
298
+ for (const k in this.draws) {
299
+ this.draws[k]?.handlers?.stage?.[event]?.(e);
300
+ }
301
+ for (const k in this.handlers) {
302
+ this.handlers[k]?.handlers?.stage?.[event]?.(e);
303
+ }
304
+ });
305
+ }
306
+
307
+ const container = this.stage.container();
308
+ container.tabIndex = 1;
309
+ container.focus();
310
+ for (const event of [
311
+ 'mouseenter',
312
+ 'dragenter',
313
+ 'mousemove',
314
+ 'mouseout',
315
+ 'dragenter',
316
+ 'dragover',
317
+ 'drop',
318
+ 'keydown',
319
+ 'keyup'
320
+ ]) {
321
+ container.addEventListener(event, (e) => {
322
+ e?.preventDefault();
323
+ if (['mouseenter', 'dragenter'].includes(event)) {
324
+ // 激活 dom 事件
325
+ this.stage.container().focus();
326
+ }
327
+ for (const k in this.draws) {
328
+ this.draws[k]?.handlers?.dom?.[event]?.(e);
329
+ }
330
+ for (const k in this.handlers) {
331
+ this.handlers[k]?.handlers?.dom?.[event]?.(e);
332
+ }
333
+ });
334
+ }
335
+
336
+ for (const event of [
337
+ 'mousedown',
338
+ 'transformstart',
339
+ 'transform',
340
+ 'transformend',
341
+ 'dragstart',
342
+ 'dragmove',
343
+ 'dragend',
344
+ 'mousemove',
345
+ 'mouseleave',
346
+ 'dblclick'
347
+ ]) {
348
+ this.transformer.on(event, (e) => {
349
+ e?.evt?.preventDefault();
350
+ for (const k in this.draws) {
351
+ this.draws[k]?.handlers?.transformer?.[event]?.(e);
352
+ }
353
+ for (const k in this.handlers) {
354
+ this.handlers[k]?.handlers?.transformer?.[event]?.(e);
355
+ }
356
+ });
357
+ }
358
+
359
+ this.handlers[SelectionHandlers.name]?.transformerConfig?.anchorDragBoundFunc &&
360
+ this.transformer.anchorDragBoundFunc(
361
+ this.handlers[SelectionHandlers.name].transformerConfig!.anchorDragBoundFunc!
362
+ );
363
+ }
364
+
365
+ // 获取 stage 状态
366
+ getStageState() {
367
+ return {
368
+ width: this.stage.width() - this.rulerSize,
369
+ height: this.stage.height() - this.rulerSize,
370
+ scale: this.stage.scaleX(),
371
+ x: this.stage.x(),
372
+ y: this.stage.y()
373
+ };
374
+ }
375
+
376
+ // 相对大小(基于 stage,且无视 scale)
377
+ toStageValue(boardPos: number) {
378
+ return boardPos / this.stage.scaleX();
379
+ }
380
+
381
+ // 绝对大小(基于可视区域像素)
382
+ toBoardValue(stagePos: number) {
383
+ return stagePos * this.stage.scaleX();
384
+ }
385
+
386
+ // 忽略非素材
387
+ ignore(node: Konva.Node) {
388
+ // 素材有各自根 group
389
+ const isGroup = node instanceof Konva.Group;
390
+ return !isGroup || this.ignoreSelect(node) || this.ignoreDraw(node) || this.ignoreLink(node);
391
+ }
392
+
393
+ // 忽略 选择时 辅助元素
394
+ ignoreSelect(node: Konva.Node) {
395
+ return node.id() === 'selectRect' || node.id() === 'hoverRect';
396
+ }
397
+
398
+ // 忽略各 draw 的根 group
399
+ ignoreDraw(node: Konva.Node) {
400
+ return [BgDraw.name, RulerDraw.name, RefLineDraw.name, ContextmenuDraw.name, PreviewDraw.name, LinkDraw.name, GraphDraw.name].includes(node.name());
401
+ }
402
+
403
+ // 忽略各 draw 的根 group
404
+ ignoreLink(node: Konva.Node) {
405
+ return ["link-anchor", "linking-line", "link-point", "link-line", "link-manual-point"].includes(node.name());
406
+ }
407
+
408
+ // 重绘(可选择)
409
+ redraw(drawNames?: string[]) {
410
+ const all = [
411
+ // layerFloor
412
+ BgDraw.name, // 更新背景
413
+ // layerCover(按先后顺序)
414
+ GraphDraw.name, // 更新图形调整点
415
+ LinkDraw.name, // 更新连线
416
+ RulerDraw.name, // 更新比例尺
417
+ RefLineDraw.name, // 更新参考线
418
+ PreviewDraw.name, // 更新预览
419
+ ContextmenuDraw.name // 更新右键菜单
420
+ ];
421
+
422
+ // 可以以此发现缺失的 draw
423
+ // console.log('redraw', drawNames)
424
+
425
+ if (Array.isArray(drawNames)) {
426
+ // 选择性 draw 也要保持顺序
427
+ for (const name of all) {
428
+ if (drawNames.includes(name)) {
429
+ this.draws[name]?.draw();
430
+ }
431
+ }
432
+ } else {
433
+ for (const name of all) {
434
+ this.draws[name]?.draw();
435
+ }
436
+ }
437
+ }
438
+
439
+ changeDraggable(disabled: boolean) {
440
+ this.layer.children.forEach((asset) => {
441
+ asset.draggable(disabled);
442
+ });
443
+ }
444
+
445
+ // 改变画图类型
446
+ changeGraphType(type?: GraphType) {
447
+ if (type) {
448
+ this.texting = false;
449
+ this.emit('texting-change', this.texting);
450
+ }
451
+ this.graphType = type;
452
+ this.emit('graph-type-change', this.graphType);
453
+ // 绘制 Graph 的时候,不允许直接拖动其他素材
454
+ this.changeDraggable(!this.config.readonly && this.graphType === void 0);
455
+ }
456
+
457
+ // 添加文字状态
458
+ changeTexting(texting: boolean) {
459
+ if (texting) {
460
+ this.graphType = undefined;
461
+ this.emit('graph-type-change', this.graphType);
462
+ }
463
+ this.texting = texting;
464
+ this.emit('texting-change', this.texting);
465
+ document.body.style.cursor = this.texting ? 'text' : 'default';
466
+ }
467
+
468
+ // 页面设置 默认值
469
+ static PageSettingsDefault: PageSettings = {
470
+ // 画布默认尺寸
471
+ pageWidth: 1280,
472
+ pageHeight: 720,
473
+ // 样式默认值
474
+ background: undefined,
475
+ stroke: 'rgb(0,0,0)',
476
+ strokeWidth: 1,
477
+ fill: 'rgb(0,0,0)',
478
+ linkStroke: 'rgb(0,0,0)',
479
+ linkStrokeWidth: 1,
480
+ fontSize: 24,
481
+ textFill: 'rgb(0,0,0)'
482
+ };
483
+
484
+ // 获取页面设置
485
+ getPageSettings(): PageSettings {
486
+ return this.stage.attrs.pageSettings ?? { ...Render.PageSettingsDefault };
487
+ }
488
+
489
+ // 更新页面设置
490
+ setPageSettings(settings: PageSettings, update = false) {
491
+ this.stage.setAttr('pageSettings', settings);
492
+ // 更新背景
493
+ this.updateBackground();
494
+ if (update) {
495
+ // 更新历史
496
+ this.updateHistory();
497
+ }
498
+ }
499
+
500
+ // 获取背景
501
+ getBackground() {
502
+ return this.draws[BgDraw.name]?.layer.findOne(`.${BgDraw.name}__background`) as Konva.Rect;
503
+ }
504
+
505
+ // 更新背景
506
+ updateBackground() {
507
+ const background = this.getBackground();
508
+ if (background) {
509
+ background.fill(this.getPageSettings().background ?? 'transparent');
510
+ }
511
+ this.draws[BgDraw.name]?.draw();
512
+ this.draws[GraphDraw.name]?.draw();
513
+ this.draws[LinkDraw.name]?.draw();
514
+ this.draws[PreviewDraw.name]?.draw();
515
+ }
516
+
517
+ // 素材设置 默认值
518
+ static AssetSettingsDefault: AssetSettings = {
519
+ stroke: '',
520
+ strokeWidth: 0,
521
+ fill: '',
522
+ arrowStart: false,
523
+ arrowEnd: false,
524
+ fontSize: 0,
525
+ textFill: '',
526
+ text: 'Text',
527
+ x: 0,
528
+ y: 0,
529
+ rotation: 0,
530
+ tension: 0
531
+ };
532
+
533
+ // 获取素材设置
534
+ getAssetSettings(asset?: Konva.Node): AssetSettings {
535
+ const base = asset?.attrs.assetSettings ?? { ...Render.AssetSettingsDefault };
536
+ return {
537
+ // 特定
538
+ ...base,
539
+ // 继承全局
540
+ stroke: base.stroke || this.getPageSettings().stroke,
541
+ strokeWidth: base.strokeWidth || this.getPageSettings().strokeWidth,
542
+ fontSize: base.fontSize || this.getPageSettings().fontSize,
543
+ textFill: base.textFill || this.getPageSettings().textFill,
544
+ // 绘制图形,默认不填充
545
+ fill:
546
+ base.fill ||
547
+ (asset?.attrs.assetType === AssetType.Graph
548
+ ? 'transparent'
549
+ : this.getPageSettings().fill),
550
+ x: parseFloat((asset?.position().x ?? 0).toFixed(1)),
551
+ y: parseFloat((asset?.position().y ?? 0).toFixed(1)),
552
+ rotation: parseFloat((asset?.rotation() ?? 0).toFixed(1)),
553
+ tension:
554
+ asset?.attrs.assetType === AssetType.Graph &&
555
+ asset?.attrs.graphType === "Curve"
556
+ ? base.tension
557
+ : undefined
558
+ };
559
+ }
560
+
561
+ // 设置 svgXML 样式(部分)
562
+ setSvgXMLSettings(xml: string, settings: AssetSettings) {
563
+ const reg = /<(circle|ellipse|line|path|polygon|rect|text|textPath|tref|tspan)[^>/]*\/?>/g;
564
+ const shapes = xml.match(reg);
565
+ const regStroke = / stroke="([^"]*)"/;
566
+ const regFill = / fill="([^"]*)"/;
567
+
568
+ for (const shape of shapes ?? []) {
569
+ let result = shape;
570
+ if (settings.stroke) {
571
+ if (regStroke.test(shape)) {
572
+ result = result.replace(regStroke, ` stroke="${settings.stroke}"`);
573
+ } else {
574
+ result = result.replace(/(<[^>/]*)(\/?>)/, `$1 stroke="${settings.stroke}" $2`);
575
+ }
576
+ }
577
+
578
+ if (settings.fill) {
579
+ if (regFill.test(shape)) {
580
+ result = result.replace(regFill, ` fill="${settings.fill}"`);
581
+ } else {
582
+ result = result.replace(/(<[^>/]*)(\/?>)/, `$1 fill="${settings.fill}" $2`);
583
+ }
584
+ }
585
+
586
+ xml = xml.replace(shape, result);
587
+ }
588
+ return xml;
589
+ }
590
+
591
+ rotatePoint({ x, y }: { x: number; y: number }, rad: number) {
592
+ const rCos = Math.cos(rad);
593
+ const rSin = Math.sin(rad);
594
+ return { x: x * rCos - y * rSin, y: y * rCos + x * rSin };
595
+ }
596
+
597
+ rotateAroundCenter(node: Konva.Node, rotation: number) {
598
+ const topLeft = { x: -node.width() / 2, y: -node.height() / 2 };
599
+ const current = this.rotatePoint(topLeft, Konva.getAngle(node.rotation()));
600
+ const rotated = this.rotatePoint(topLeft, Konva.getAngle(rotation));
601
+ const dx = rotated.x - current.x;
602
+ const dy = rotated.y - current.y;
603
+
604
+ node.rotation(rotation);
605
+ node.x(node.x() + dx);
606
+ node.y(node.y() + dy);
607
+ }
608
+
609
+ // 更新素材设置
610
+ async setAssetSettings(asset: Konva.Node, settings: AssetSettings, update = false) {
611
+ asset.setAttr('assetSettings', settings);
612
+ if (asset instanceof Konva.Group) {
613
+ if (asset.attrs.imageType === ImageType.svg) {
614
+ const node = asset.children[0] as Konva.Shape;
615
+ if (node instanceof Konva.Image) {
616
+ if (node.attrs.svgXML) {
617
+ const n = await this.assetTool.loadSvgXML(
618
+ this.setSvgXMLSettings(node.attrs.svgXML, settings)
619
+ );
620
+ node.parent?.add(n);
621
+ node.remove();
622
+ node.destroy();
623
+ n.zIndex(0);
624
+ }
625
+ }
626
+ } else if (asset.attrs.assetType === AssetType.Graph) {
627
+ const node = asset.findOne('.graph');
628
+ if (node instanceof Konva.Shape) {
629
+ node.strokeWidth(settings.strokeWidth);
630
+ node.stroke(settings.stroke);
631
+ if (node instanceof Konva.Arrow) {
632
+ // 箭头跟随 stroke
633
+ node.fill(settings.stroke);
634
+ } else {
635
+ node.fill(settings.fill);
636
+ }
637
+ if (node instanceof Konva.Arrow) {
638
+ node.pointerAtBeginning(settings.arrowStart);
639
+ node.pointerAtEnding(settings.arrowEnd);
640
+ }
641
+ if (node instanceof Konva.Arrow && asset.attrs.graphType === "Curve") {
642
+ node.tension(settings.tension);
643
+ }
644
+ }
645
+ } else if (asset.attrs.assetType === AssetType.Text) {
646
+ const node = asset.findOne('Text');
647
+ const rect = asset.findOne('Rect');
648
+ if (node instanceof Konva.Text && rect instanceof Konva.Rect) {
649
+ let sizeChanged = false;
650
+ if (node.fontSize() !== settings.fontSize || node.text() !== settings.text) {
651
+ sizeChanged = true;
652
+ }
653
+
654
+ node.fill(settings.textFill);
655
+ node.fontSize(settings.fontSize);
656
+ node.text(settings.text);
657
+
658
+ // 内容为空时,给一个半透明背景色
659
+ rect.fill(node.text().trim() ? '' : 'rgba(0,0,0,0.1)');
660
+ rect.width(Math.max(node.width(), settings.fontSize));
661
+ rect.height(Math.max(node.height(), settings.fontSize));
662
+
663
+ // 刷新 transformer 大小
664
+ if (sizeChanged) {
665
+ this.selectionTool.select([asset]);
666
+ }
667
+ }
668
+ }
669
+
670
+ // rotate 会影响 position,不能同时改变
671
+ // 区分属性面板正在调整
672
+ if (Math.abs(settings.rotation - asset.rotation()) >= 0.1) {
673
+ this.rotateAroundCenter(asset, settings.rotation);
674
+ // 同步 position 的变化
675
+ this.emit('asset-position-change', [asset]);
676
+ } else {
677
+ const prevSettings = this.getAssetSettings(asset);
678
+ asset.position({
679
+ x: parseFloat(settings.x.toFixed(1)),
680
+ y: parseFloat(settings.y.toFixed(1))
681
+ });
682
+ // 外部调用变化同步
683
+ if (settings.x !== prevSettings.x || settings.y !== prevSettings.y) {
684
+ this.emit('asset-position-change', [asset]);
685
+ }
686
+ }
687
+ }
688
+
689
+ if (update) {
690
+ // 更新历史
691
+ this.updateHistory();
692
+ }
693
+
694
+ this.draws[BgDraw.name]?.draw();
695
+ this.draws[GraphDraw.name]?.draw();
696
+ this.draws[LinkDraw.name]?.draw();
697
+ this.draws[PreviewDraw.name]?.draw();
698
+ }
699
+
700
+ // 连接线设置 默认值
701
+ static LinkSettingsDefault: LinkSettings = {
702
+ stroke: '',
703
+ strokeWidth: 0,
704
+ arrowStart: false,
705
+ arrowEnd: false,
706
+ tension: 0
707
+ };
708
+
709
+ // 连接线设置
710
+ async setLinkSettings(link: Konva.Line, settings: LinkSettings, update = false) {
711
+ const group = this.layer.findOne(`#${link.attrs.groupId}`);
712
+ if (Array.isArray(group?.attrs.points)) {
713
+ const point = (group?.attrs.points as LinkDrawPoint[]).find(
714
+ (o: LinkDrawPoint) => o.id === link.attrs.pointId
715
+ );
716
+ if (point) {
717
+ const pair = point.pairs.find((o) => o.id === link.attrs.pairId);
718
+ if (pair) {
719
+ pair.style = {
720
+ ...pair.style,
721
+ ...settings,
722
+ strokeWidth: Number(settings.strokeWidth ?? pair.style.strokeWidth),
723
+ };
724
+ group.setAttr('points', group?.attrs.points);
725
+ }
726
+ }
727
+ }
728
+
729
+ if (update) {
730
+ // 更新历史
731
+ this.updateHistory();
732
+ }
733
+
734
+ this.draws[BgDraw.name]?.draw();
735
+ this.draws[GraphDraw.name]?.draw();
736
+ this.draws[LinkDraw.name]?.draw();
737
+ this.draws[PreviewDraw.name]?.draw();
738
+ }
739
+
740
+ // 获取连接线设置
741
+ getLinkSettings(link?: Konva.Line): LinkSettings {
742
+ let settings: (Konva.LineConfig & LinkSettings) | undefined = undefined;
743
+ if (link) {
744
+ const group = this.layer.findOne(`#${link.attrs.groupId}`);
745
+ if (Array.isArray(group?.attrs.points)) {
746
+ const point = (group?.attrs.points as LinkDrawPoint[]).find(
747
+ (o: LinkDrawPoint) => o.id === link.attrs.pointId
748
+ );
749
+ if (point) {
750
+ const pair = point.pairs.find((o) => o.id === link.attrs.pairId);
751
+ if (pair) {
752
+ settings = pair.style;
753
+ }
754
+ }
755
+ }
756
+ }
757
+
758
+ const base = settings ?? { ...Render.LinkSettingsDefault };
759
+
760
+ return {
761
+ // 特定
762
+ ...base,
763
+ // 继承全局
764
+ stroke: (base.stroke as string) || this.getPageSettings().linkStroke,
765
+ strokeWidth: base.strokeWidth || this.getPageSettings().linkStrokeWidth
766
+ };
767
+ }
768
+ }