aldehyde 0.2.472 → 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 (116) hide show
  1. package/lib/controls/entity-select/entity-select.js +1 -1
  2. package/lib/controls/entity-select/entity-select.js.map +1 -1
  3. package/lib/controls/entry-control.js +2 -2
  4. package/lib/controls/entry-control.js.map +1 -1
  5. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +47 -3
  6. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js +12 -12
  7. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js.map +1 -1
  8. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +77 -0
  9. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.ttf +0 -0
  10. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff +0 -0
  11. package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff2 +0 -0
  12. package/lib/draw-canvas/edit/components/asset-bar/index.d.ts +5 -0
  13. package/lib/draw-canvas/edit/components/asset-bar/index.d.ts.map +1 -0
  14. package/lib/draw-canvas/edit/components/asset-bar/index.js +78 -0
  15. package/lib/draw-canvas/edit/components/asset-bar/index.js.map +1 -0
  16. package/lib/draw-canvas/edit/components/asset-bar/index.less +36 -0
  17. package/lib/draw-canvas/edit/components/main-header/index.d.ts +14 -0
  18. package/lib/draw-canvas/edit/components/main-header/index.d.ts.map +1 -0
  19. package/lib/draw-canvas/edit/components/main-header/index.js +163 -0
  20. package/lib/draw-canvas/edit/components/main-header/index.js.map +1 -0
  21. package/lib/draw-canvas/edit/components/main-header/index.less +21 -0
  22. package/lib/draw-canvas/edit/components/render/index.d.ts +86 -0
  23. package/lib/draw-canvas/edit/components/render/index.d.ts.map +1 -0
  24. package/lib/draw-canvas/edit/components/render/index.js +686 -0
  25. package/lib/draw-canvas/edit/components/render/index.js.map +1 -0
  26. package/lib/draw-canvas/edit/components/render/types.d.ts +243 -0
  27. package/lib/draw-canvas/edit/components/render/types.d.ts.map +1 -0
  28. package/lib/draw-canvas/edit/components/render/types.js +66 -0
  29. package/lib/draw-canvas/edit/components/render/types.js.map +1 -0
  30. package/lib/draw-canvas/edit/components/setting-form/index.d.ts +19 -0
  31. package/lib/draw-canvas/edit/components/setting-form/index.d.ts.map +1 -0
  32. package/lib/draw-canvas/edit/components/setting-form/index.js +164 -0
  33. package/lib/draw-canvas/edit/components/setting-form/index.js.map +1 -0
  34. package/lib/draw-canvas/edit/index.d.ts +5 -0
  35. package/lib/draw-canvas/edit/index.d.ts.map +1 -0
  36. package/lib/draw-canvas/edit/index.js +112 -0
  37. package/lib/draw-canvas/edit/index.js.map +1 -0
  38. package/lib/draw-canvas/edit/index.less +34 -0
  39. package/lib/form/form-Item-group.d.ts.map +1 -1
  40. package/lib/form/form-Item-group.js +1 -1
  41. package/lib/form/form-Item-group.js.map +1 -1
  42. package/lib/icon/local-aliIcon/iconfont.js +5 -5
  43. package/lib/icon/local-aliIcon/iconfont.js.map +1 -1
  44. package/lib/table/relation-table.d.ts +4 -0
  45. package/lib/table/relation-table.d.ts.map +1 -1
  46. package/lib/tmpl/hcservice-v3.d.ts +1 -0
  47. package/lib/tmpl/hcservice-v3.d.ts.map +1 -1
  48. package/lib/tmpl/hcservice-v3.js +27 -0
  49. package/lib/tmpl/hcservice-v3.js.map +1 -1
  50. package/lib/tmpl/interface.d.ts +4 -0
  51. package/lib/tmpl/interface.d.ts.map +1 -1
  52. package/lib/tmpl/interface.js.map +1 -1
  53. package/lib/units/index.d.ts +1 -0
  54. package/lib/units/index.d.ts.map +1 -1
  55. package/lib/units/index.js +16 -0
  56. package/lib/units/index.js.map +1 -1
  57. package/package.json +1 -1
  58. package/src/aldehyde/controls/entity-select/entity-select.tsx +1 -1
  59. package/src/aldehyde/controls/entry-control.tsx +2 -2
  60. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +47 -3
  61. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js +1 -1
  62. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +77 -0
  63. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.ttf +0 -0
  64. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff +0 -0
  65. package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff2 +0 -0
  66. package/src/aldehyde/draw-canvas/edit/components/asset-bar/index.less +36 -0
  67. package/src/aldehyde/draw-canvas/edit/components/asset-bar/index.tsx +93 -0
  68. package/src/aldehyde/draw-canvas/edit/components/main-header/index.less +21 -0
  69. package/src/aldehyde/draw-canvas/edit/components/main-header/index.tsx +187 -0
  70. package/src/aldehyde/draw-canvas/edit/components/render/draws/bg-draw.ts +98 -0
  71. package/src/aldehyde/draw-canvas/edit/components/render/draws/contextmenu-draw.ts +307 -0
  72. package/src/aldehyde/draw-canvas/edit/components/render/draws/graph-draw.ts +251 -0
  73. package/src/aldehyde/draw-canvas/edit/components/render/draws/index.ts +7 -0
  74. package/src/aldehyde/draw-canvas/edit/components/render/draws/link-draw.ts +1416 -0
  75. package/src/aldehyde/draw-canvas/edit/components/render/draws/preview-draw.ts +257 -0
  76. package/src/aldehyde/draw-canvas/edit/components/render/draws/ref-line-draw.ts +72 -0
  77. package/src/aldehyde/draw-canvas/edit/components/render/draws/ruler-draw.ts +167 -0
  78. package/src/aldehyde/draw-canvas/edit/components/render/graphs/base-graph.ts +241 -0
  79. package/src/aldehyde/draw-canvas/edit/components/render/graphs/bezier.ts +542 -0
  80. package/src/aldehyde/draw-canvas/edit/components/render/graphs/circle.ts +700 -0
  81. package/src/aldehyde/draw-canvas/edit/components/render/graphs/curve.ts +501 -0
  82. package/src/aldehyde/draw-canvas/edit/components/render/graphs/index.ts +6 -0
  83. package/src/aldehyde/draw-canvas/edit/components/render/graphs/line.ts +494 -0
  84. package/src/aldehyde/draw-canvas/edit/components/render/graphs/rect.ts +681 -0
  85. package/src/aldehyde/draw-canvas/edit/components/render/handlers/drag-handlers.ts +69 -0
  86. package/src/aldehyde/draw-canvas/edit/components/render/handlers/drag-outside-handlers.ts +162 -0
  87. package/src/aldehyde/draw-canvas/edit/components/render/handlers/graph-handlers.ts +108 -0
  88. package/src/aldehyde/draw-canvas/edit/components/render/handlers/index.ts +9 -0
  89. package/src/aldehyde/draw-canvas/edit/components/render/handlers/key-move-handlers.ts +50 -0
  90. package/src/aldehyde/draw-canvas/edit/components/render/handlers/link-handlers.ts +46 -0
  91. package/src/aldehyde/draw-canvas/edit/components/render/handlers/selection-handlers.ts +385 -0
  92. package/src/aldehyde/draw-canvas/edit/components/render/handlers/shutcut-handlers.ts +46 -0
  93. package/src/aldehyde/draw-canvas/edit/components/render/handlers/text-handlers.ts +82 -0
  94. package/src/aldehyde/draw-canvas/edit/components/render/handlers/zoom-handlers.ts +60 -0
  95. package/src/aldehyde/draw-canvas/edit/components/render/index.ts +768 -0
  96. package/src/aldehyde/draw-canvas/edit/components/render/tools/align-tool.ts +91 -0
  97. package/src/aldehyde/draw-canvas/edit/components/render/tools/asset-tool.ts +142 -0
  98. package/src/aldehyde/draw-canvas/edit/components/render/tools/attract-tool.ts +440 -0
  99. package/src/aldehyde/draw-canvas/edit/components/render/tools/copy-tool.ts +269 -0
  100. package/src/aldehyde/draw-canvas/edit/components/render/tools/import-export-tool.ts +603 -0
  101. package/src/aldehyde/draw-canvas/edit/components/render/tools/index.ts +9 -0
  102. package/src/aldehyde/draw-canvas/edit/components/render/tools/link-tool.ts +225 -0
  103. package/src/aldehyde/draw-canvas/edit/components/render/tools/position-tool.ts +212 -0
  104. package/src/aldehyde/draw-canvas/edit/components/render/tools/selection-tool.ts +132 -0
  105. package/src/aldehyde/draw-canvas/edit/components/render/tools/z-index-tool.ts +227 -0
  106. package/src/aldehyde/draw-canvas/edit/components/render/types.ts +287 -0
  107. package/src/aldehyde/draw-canvas/edit/components/render/utils/a-star.ts +116 -0
  108. package/src/aldehyde/draw-canvas/edit/components/render/utils/bezier-scene-func.ts +73 -0
  109. package/src/aldehyde/draw-canvas/edit/components/setting-form/index.tsx +200 -0
  110. package/src/aldehyde/draw-canvas/edit/index.less +34 -0
  111. package/src/aldehyde/draw-canvas/edit/index.tsx +138 -0
  112. package/src/aldehyde/form/form-Item-group.tsx +1 -0
  113. package/src/aldehyde/icon/local-aliIcon/iconfont.js +1 -1
  114. package/src/aldehyde/tmpl/hcservice-v3.tsx +14 -0
  115. package/src/aldehyde/tmpl/interface.tsx +2 -0
  116. 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
+ }