@logicflow/extension 2.0.11 → 2.0.13

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 (63) hide show
  1. package/.turbo/turbo-build.log +34 -34
  2. package/CHANGELOG.md +23 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/components/mini-map/index.d.ts +2 -0
  7. package/es/components/mini-map/index.js +10 -0
  8. package/es/dynamic-group/index.d.ts +2 -1
  9. package/es/dynamic-group/index.js +21 -19
  10. package/es/index.css +1 -1
  11. package/es/index.d.ts +1 -0
  12. package/es/index.js +1 -0
  13. package/es/materials/group/GroupNode.d.ts +5 -5
  14. package/es/materials/group/GroupNode.js +3 -3
  15. package/es/materials/group/index.js +5 -5
  16. package/es/materials/node-selection/index.d.ts +6 -6
  17. package/es/materials/node-selection/index.js +90 -10
  18. package/es/style/index.css +1 -1
  19. package/es/style/raw.d.ts +1 -1
  20. package/es/style/raw.js +1 -1
  21. package/es/tools/label/Label.d.ts +4 -0
  22. package/es/tools/label/Label.js +75 -31
  23. package/es/tools/label/LabelModel.js +1 -0
  24. package/es/tools/label/index.d.ts +1 -0
  25. package/es/tools/label/index.js +47 -3
  26. package/es/tools/proximity-connect/index.d.ts +42 -0
  27. package/es/tools/proximity-connect/index.js +337 -0
  28. package/lib/components/mini-map/index.d.ts +2 -0
  29. package/lib/components/mini-map/index.js +10 -0
  30. package/lib/dynamic-group/index.d.ts +2 -1
  31. package/lib/dynamic-group/index.js +21 -19
  32. package/lib/index.css +1 -1
  33. package/lib/index.d.ts +1 -0
  34. package/lib/index.js +1 -0
  35. package/lib/materials/group/GroupNode.d.ts +5 -5
  36. package/lib/materials/group/GroupNode.js +3 -3
  37. package/lib/materials/group/index.js +5 -5
  38. package/lib/materials/node-selection/index.d.ts +6 -6
  39. package/lib/materials/node-selection/index.js +89 -9
  40. package/lib/style/index.css +1 -1
  41. package/lib/style/raw.d.ts +1 -1
  42. package/lib/style/raw.js +1 -1
  43. package/lib/tools/label/Label.d.ts +4 -0
  44. package/lib/tools/label/Label.js +75 -31
  45. package/lib/tools/label/LabelModel.js +1 -0
  46. package/lib/tools/label/index.d.ts +1 -0
  47. package/lib/tools/label/index.js +46 -2
  48. package/lib/tools/proximity-connect/index.d.ts +42 -0
  49. package/lib/tools/proximity-connect/index.js +340 -0
  50. package/package.json +3 -3
  51. package/src/components/mini-map/index.ts +11 -0
  52. package/src/dynamic-group/index.ts +29 -8
  53. package/src/index.ts +1 -0
  54. package/src/materials/group/GroupNode.ts +3 -3
  55. package/src/materials/group/index.ts +5 -5
  56. package/src/materials/node-selection/index.ts +115 -14
  57. package/src/style/index.less +3 -5
  58. package/src/style/raw.ts +3 -7
  59. package/src/tools/label/Label.tsx +106 -55
  60. package/src/tools/label/LabelModel.ts +1 -0
  61. package/src/tools/label/index.ts +64 -3
  62. package/src/tools/proximity-connect/index.ts +399 -0
  63. package/stats.html +1 -1
@@ -79,26 +79,31 @@ var Label = /** @class */ (function (_super) {
79
79
  var _a;
80
80
  var _b = _this.props, label = _b.label, graphModel = _b.graphModel;
81
81
  var nodeTextDraggable = graphModel.editConfigModel.nodeTextDraggable;
82
- // 当 label 允许拖拽 且不处于拖拽状态时, StepDrag 开启拖拽
83
- if (((_a = label.draggable) !== null && _a !== void 0 ? _a : nodeTextDraggable) && !_this.state.isDragging) {
84
- _this.setState({ isDragging: true });
82
+ // 当 label 允许拖拽 且不处于拖拽状态、不处于编辑状态时, StepDrag 开启拖拽
83
+ if (((_a = label.draggable) !== null && _a !== void 0 ? _a : nodeTextDraggable) &&
84
+ !_this.state.isDragging &&
85
+ !_this.state.isEditing) {
85
86
  _this.stepDrag.handleMouseDown(e);
86
87
  }
87
88
  };
89
+ _this.handleMouseUp = function (e) {
90
+ if (_this.state.isDragging) {
91
+ _this.stepDrag.handleMouseUp(e);
92
+ }
93
+ };
88
94
  _this.handleDragging = function (_a) {
89
95
  var deltaX = _a.deltaX, deltaY = _a.deltaY;
90
- var _b = _this.props, label = _b.label, element = _b.element, graphModel = _b.graphModel;
96
+ if (!_this.state.isDragging) {
97
+ _this.setState({ isDragging: true });
98
+ }
99
+ var _b = _this.props, label = _b.label, graphModel = _b.graphModel;
91
100
  // DONE: 添加缩放时拖拽的逻辑,对 deltaX 和 deltaY 进行按比例缩放
92
101
  var transformModel = graphModel.transformModel;
93
102
  var _c = __read(transformModel.fixDeltaXY(deltaX, deltaY), 2), curDeltaX = _c[0], curDeltaY = _c[1];
94
- // DONE:更新 label 位置,触发 LABEL:DRAG 事件,并抛出相关的数据
95
- var _label = element.properties._label;
96
- var elementLabel = _label;
97
- var idx = (0, lodash_es_1.findIndex)(elementLabel, function (cur) { return cur.id === label.id; });
98
- var target = elementLabel[idx];
99
- elementLabel[idx] = __assign(__assign({}, target), { x: target.x + curDeltaX, y: target.y + curDeltaY });
100
- var targetElem = graphModel.getElement(element.id);
101
- targetElem === null || targetElem === void 0 ? void 0 : targetElem.setProperty('_label', elementLabel);
103
+ _this.setElementModelLabelInfo({
104
+ x: label.x + curDeltaX,
105
+ y: label.y + curDeltaY,
106
+ });
102
107
  graphModel.eventCenter.emit('label:drag', {
103
108
  data: label.getData(),
104
109
  model: label,
@@ -107,6 +112,20 @@ var Label = /** @class */ (function (_super) {
107
112
  _this.handleDragEnd = function () {
108
113
  _this.setState({ isDragging: false });
109
114
  };
115
+ _this.handleClick = function (e) {
116
+ var _a = _this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
117
+ // 更新当前Label选中状态
118
+ element.setSelected(!_this.state.isSelected);
119
+ _this.setState({ isSelected: !_this.state.isSelected });
120
+ _this.setElementModelLabelInfo({
121
+ isSelected: true,
122
+ });
123
+ graphModel.eventCenter.emit('label:click', {
124
+ data: label.getData(),
125
+ e: e,
126
+ model: element,
127
+ });
128
+ };
110
129
  _this.handleDbClick = function (e) {
111
130
  var _a = _this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
112
131
  graphModel.eventCenter.emit('label:dblclick', {
@@ -145,6 +164,7 @@ var Label = /** @class */ (function (_super) {
145
164
  _this.setState({
146
165
  isDragging: false,
147
166
  isHovered: false,
167
+ isSelected: false,
148
168
  });
149
169
  };
150
170
  // 重新计算 Label 大小
@@ -162,32 +182,56 @@ var Label = /** @class */ (function (_super) {
162
182
  isEditing: false,
163
183
  isHovered: false,
164
184
  isDragging: false,
185
+ isSelected: false,
165
186
  };
166
187
  return _this;
167
188
  }
189
+ Label.prototype.setElementModelLabelInfo = function (data) {
190
+ var _a = this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
191
+ var _label = element.properties._label;
192
+ var elementLabel = _label;
193
+ var idx = (0, lodash_es_1.findIndex)(elementLabel, function (cur) { return cur.id === label.id; });
194
+ var target = elementLabel[idx];
195
+ elementLabel[idx] = __assign(__assign({}, target), data);
196
+ var targetElem = graphModel.getElement(element.id);
197
+ targetElem === null || targetElem === void 0 ? void 0 : targetElem.setProperty('_label', elementLabel);
198
+ };
168
199
  // TODO:如何处理 Label zIndex 的问题, Label 永远会比节点层级高
169
200
  // 当 Label 被元素遮盖时,隐藏它
170
201
  Label.prototype.componentDidMount = function () {
171
202
  var _this = this;
172
203
  var _a = this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
173
204
  // 在点击元素、边或者画布 时,结束 Label 的编辑态
174
- graphModel.eventCenter.on('blank:click,node:click,edge:click', function () {
175
- var _a, _b, _c, _d;
176
- // 如果当前 label 处于编辑态,则结束编辑态
177
- if (_this.state.isEditing) {
205
+ graphModel.eventCenter.on('blank:click,node:click,edge:click,label:click', function (_a) {
206
+ var _b, _c, _d, _e;
207
+ var data = _a.data;
208
+ // 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 处于选中态
209
+ // 则取消选中态
210
+ if ((data === null || data === void 0 ? void 0 : data.type) !== 'label' ||
211
+ (data.type === 'label' && data.id !== label.id) ||
212
+ _this.state.isSelected) {
213
+ _this.setState({ isSelected: false });
214
+ }
215
+ // 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 处于编辑态
216
+ // 则结束编辑态
217
+ if (((data === null || data === void 0 ? void 0 : data.type) !== 'label' ||
218
+ (data.type == 'label' && data.id !== label.id)) &&
219
+ _this.state.isEditing) {
178
220
  _this.setState({ isEditing: false });
179
- var value = (_b = (_a = _this.textRef.current) === null || _a === void 0 ? void 0 : _a.innerText) !== null && _b !== void 0 ? _b : '';
180
- var content = (_d = (_c = _this.textRef.current) === null || _c === void 0 ? void 0 : _c.innerHTML) !== null && _d !== void 0 ? _d : '';
181
- var _label = element.properties._label;
182
- var elementLabel = _label;
183
- var idx = (0, lodash_es_1.findIndex)(elementLabel, function (cur) { return cur.id === label.id; });
184
- var target = elementLabel[idx];
185
- elementLabel[idx] = __assign(__assign({}, target), { value: value, content: content });
186
- var targetElem = graphModel.getElement(element.id);
187
- targetElem === null || targetElem === void 0 ? void 0 : targetElem.setProperty('_label', elementLabel);
221
+ var value = (_c = (_b = _this.textRef.current) === null || _b === void 0 ? void 0 : _b.innerText) !== null && _c !== void 0 ? _c : '';
222
+ var content = (_e = (_d = _this.textRef.current) === null || _d === void 0 ? void 0 : _d.innerHTML) !== null && _e !== void 0 ? _e : '';
223
+ _this.setElementModelLabelInfo({
224
+ value: value,
225
+ content: content,
226
+ isSelected: false,
227
+ });
188
228
  element.setElementState(core_1.ElementState.DEFAULT);
189
229
  }
190
- if (_this.textRef.current) {
230
+ // 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 的文本DOM存在
231
+ // 则结束文本DOM的编辑态
232
+ if (((data === null || data === void 0 ? void 0 : data.type) !== 'label' ||
233
+ (data.type == 'label' && data.id !== label.id)) &&
234
+ _this.textRef.current) {
191
235
  _this.textRef.current.contentEditable = 'false';
192
236
  }
193
237
  });
@@ -200,7 +244,7 @@ var Label = /** @class */ (function (_super) {
200
244
  };
201
245
  Label.prototype.componentDidUpdate = function () {
202
246
  // snapshot: any, // previousState: Readonly<ILabelState>, // previousProps: Readonly<ILabelProps>,
203
- console.log('Label componentDidUpdate');
247
+ // console.log('Label componentDidUpdate')
204
248
  // console.log('previousProps', previousProps)
205
249
  // console.log('previousState', previousState)
206
250
  // console.log('snapshot', snapshot)
@@ -214,7 +258,7 @@ var Label = /** @class */ (function (_super) {
214
258
  Label.prototype.render = function () {
215
259
  var _a;
216
260
  var _b = this.props, label = _b.label, element = _b.element, graphModel = _b.graphModel;
217
- var _c = this.state, isDragging = _c.isDragging, isHovered = _c.isHovered, isEditing = _c.isEditing;
261
+ var _c = this.state, isDragging = _c.isDragging, isHovered = _c.isHovered, isSelected = _c.isSelected, isEditing = _c.isEditing;
218
262
  var transformModel = graphModel.transformModel;
219
263
  var transform = transformModel.getTransformStyle().transform;
220
264
  var id = label.id, x = label.x, y = label.y, zIndex = label.zIndex, vertical = label.vertical, style = label.style, rotate = label.rotate, content = label.content, labelWidth = label.labelWidth, textOverflowMode = label.textOverflowMode;
@@ -229,13 +273,13 @@ var Label = /** @class */ (function (_super) {
229
273
  ? "".concat(transform, " rotate(").concat(rotate, "deg)")
230
274
  : "".concat(transform, " rotate(").concat(vertical ? -0.25 : 0, "turn)"),
231
275
  };
232
- return ((0, jsx_runtime_1.jsx)("div", { id: "element-container-".concat(id), className: (0, classnames_1.default)('lf-label-editor-container'), style: containerStyle, onMouseDown: this.handleMouseDown, onDblClick: this.handleDbClick, onBlur: this.handleBlur, onMouseEnter: this.setHoverOn, onMouseOver: this.setHoverOn, onMouseLeave: this.setHoverOff, children: (0, jsx_runtime_1.jsx)("div", { ref: this.textRef, id: "editor-container-".concat(id), className: (0, classnames_1.default)('lf-label-editor', (_a = {
276
+ return ((0, jsx_runtime_1.jsx)("div", { id: "element-container-".concat(id), className: (0, classnames_1.default)('lf-label-editor-container'), style: containerStyle, onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, onClick: this.handleClick, onDblClick: this.handleDbClick, onBlur: this.handleBlur, onMouseEnter: this.setHoverOn, onMouseOver: this.setHoverOn, onMouseLeave: this.setHoverOff, children: (0, jsx_runtime_1.jsx)("div", { ref: this.textRef, id: "editor-container-".concat(id), className: (0, classnames_1.default)('lf-label-editor', (_a = {
233
277
  'lf-label-editor-dragging': isDragging,
234
278
  'lf-label-editor-editing': isEditing,
235
- 'lf-label-editor-hover': !isEditing && isHovered
279
+ 'lf-label-editor-hover': !isEditing && (isHovered || isSelected)
236
280
  },
237
281
  _a["lf-label-editor-".concat(textOverflowMode)] = !isEditing,
238
- _a)), style: __assign({ maxWidth: "".concat(maxLabelWidth, "px"), width: "".concat(maxLabelWidth, "px") }, style), dangerouslySetInnerHTML: { __html: content } }) }));
282
+ _a)), style: __assign({ maxWidth: "".concat(maxLabelWidth, "px"), boxSizing: 'border-box', display: 'inline-block', background: isEditing || element.BaseType === 'edge' ? '#fff' : 'transparent' }, style), dangerouslySetInnerHTML: { __html: content } }) }));
239
283
  };
240
284
  Label = __decorate([
241
285
  core_1.observer
@@ -35,6 +35,7 @@ var LabelModel = /** @class */ (function () {
35
35
  id: this.id,
36
36
  x: this.x,
37
37
  y: this.y,
38
+ type: 'label',
38
39
  content: this.content,
39
40
  value: this.value,
40
41
  rotate: this.rotate,
@@ -49,6 +49,7 @@ export declare class Label implements Extension {
49
49
  * @param element
50
50
  */
51
51
  private rewriteInnerMethods;
52
+ private rewriteShortcut;
52
53
  /**
53
54
  * 更新当前渲染使用的 Text or Label 模式
54
55
  */
@@ -37,7 +37,7 @@ var Label = /** @class */ (function () {
37
37
  // TODO: 2. 做一些插件需要的事件监听
38
38
  this.addEventListeners();
39
39
  // TODO: 3. 自定义快捷键,比如 delete,选中 label 时,移除 label
40
- // this.rewriteShortcut()
40
+ this.rewriteShortcut();
41
41
  // 插件中注册 LabelOverlay 工具,用于 label 的编辑
42
42
  lf.tool.registerTool(LabelOverlay_1.default.toolName, LabelOverlay_1.default);
43
43
  // LabelOverlay 和 TextEditTool 互斥,所以将它 disable 掉
@@ -277,7 +277,51 @@ var Label = /** @class */ (function () {
277
277
  };
278
278
  // TODO: others methods ???
279
279
  };
280
- // private rewriteShortcut() {}
280
+ Label.prototype.rewriteShortcut = function () {
281
+ var _this = this;
282
+ var _a = this.lf, keyboard = _a.keyboard, graphModel = _a.graphModel;
283
+ var keyboardOptions = keyboard.options.keyboard;
284
+ keyboard.off(['backspace']);
285
+ keyboard.on(['backspace'], function () {
286
+ if (!(keyboardOptions === null || keyboardOptions === void 0 ? void 0 : keyboardOptions.enabled))
287
+ return true;
288
+ if (graphModel.textEditElement)
289
+ return true;
290
+ var elements = graphModel.getSelectElements(true);
291
+ _this.lf.clearSelectElements();
292
+ var editConfigModel = _this.lf.graphModel.editConfigModel;
293
+ elements.edges.forEach(function (edge) {
294
+ var properties = edge.properties;
295
+ if (properties &&
296
+ !(0, lodash_es_1.isEmpty)(properties._label) &&
297
+ editConfigModel.textMode === core_1.TextMode.LABEL) {
298
+ var newLabelList = properties._label.filter(function (label) { return !label.isSelected; });
299
+ // 如果两个labelList长度不一致,说明有选中的元素,此时backspace做的动作是删除label
300
+ if (!(0, lodash_es_1.isEqual)(newLabelList.length, properties._label.length)) {
301
+ var edgeModel = graphModel.getEdgeModelById(edge.id);
302
+ edgeModel === null || edgeModel === void 0 ? void 0 : edgeModel.setProperty('_label', newLabelList);
303
+ return;
304
+ }
305
+ }
306
+ edge.id && _this.lf.deleteEdge(edge.id);
307
+ });
308
+ elements.nodes.forEach(function (node) {
309
+ var properties = node.properties;
310
+ if (properties &&
311
+ !(0, lodash_es_1.isEmpty)(properties._label) &&
312
+ editConfigModel.textMode === core_1.TextMode.LABEL) {
313
+ var newLabelList = properties._label.filter(function (label) { return !label.isSelected; });
314
+ if (!(0, lodash_es_1.isEqual)(newLabelList.length, properties._label.length)) {
315
+ var nodeModel = graphModel.getNodeModelById(node.id);
316
+ nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.setProperty('_label', newLabelList);
317
+ return;
318
+ }
319
+ }
320
+ node.id && _this.lf.deleteNode(node.id);
321
+ });
322
+ return false;
323
+ });
324
+ };
281
325
  /**
282
326
  * 更新当前渲染使用的 Text or Label 模式
283
327
  */
@@ -0,0 +1,42 @@
1
+ import LogicFlow, { Model, BaseNodeModel, BaseEdgeModel } from '@logicflow/core';
2
+ import AnchorConfig = Model.AnchorConfig;
3
+ import Point = LogicFlow.Point;
4
+ export type ProximityConnectProps = {
5
+ enable: boolean;
6
+ distance: number;
7
+ reverseDirection: boolean;
8
+ virtualEdgeStyle: Record<string, unknown>;
9
+ };
10
+ export declare class ProximityConnect {
11
+ static pluginName: string;
12
+ enable: boolean;
13
+ lf: LogicFlow;
14
+ closestNode?: BaseNodeModel;
15
+ currentDistance: number;
16
+ thresholdDistance: number;
17
+ currentNode?: BaseNodeModel;
18
+ reverseDirection: boolean;
19
+ currentAnchor?: AnchorConfig;
20
+ closestAnchor?: AnchorConfig;
21
+ virtualEdge?: BaseEdgeModel;
22
+ virtualEdgeStyle: Record<string, unknown>;
23
+ constructor({ lf, options, }: LogicFlow.IExtensionProps & {
24
+ options: ProximityConnectProps;
25
+ });
26
+ render(): void;
27
+ addEventListeners(): void;
28
+ handleNodeDrag(): void;
29
+ handleDrop(): void;
30
+ handleAnchorDrag(clientX: number, clientY: number): void;
31
+ findClosestAnchorOfNode(draggingNode: BaseNodeModel, allNodes: BaseNodeModel[]): void;
32
+ findClosestAnchorOfAnchor(draggingPoint: Point, allNodes: BaseNodeModel[]): void;
33
+ anchorAllowConnect(node: BaseNodeModel, anchor: AnchorConfig, draggingAnchor: AnchorConfig | undefined): boolean | undefined;
34
+ sameEdgeIsExist(edge: BaseEdgeModel): boolean;
35
+ addVirtualEdge(): void;
36
+ addActualEdge(): void;
37
+ setVirtualEdgeStyle(value: Record<string, unknown>): void;
38
+ setThresholdDistance(distance: number): void;
39
+ setReverseDirection(value: boolean): void;
40
+ setEnable(enable: boolean): void;
41
+ resetData(): void;
42
+ }
@@ -0,0 +1,340 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.ProximityConnect = void 0;
15
+ var core_1 = require("@logicflow/core");
16
+ var lodash_es_1 = require("lodash-es");
17
+ var ProximityConnect = /** @class */ (function () {
18
+ function ProximityConnect(_a) {
19
+ var lf = _a.lf, options = _a.options;
20
+ this.enable = true;
21
+ this.currentDistance = Infinity; // 当前间距
22
+ this.thresholdDistance = 100; // 节点-节点连接距离阈值
23
+ this.reverseDirection = false; // 节点-节点连线方向,默认是拖拽节点连向最近节点
24
+ this.virtualEdgeStyle = {
25
+ strokeDasharray: '10,10',
26
+ stroke: '#acacac',
27
+ }; // 虚拟边样式
28
+ this.lf = lf;
29
+ (0, lodash_es_1.assign)(this, options);
30
+ }
31
+ ProximityConnect.prototype.render = function () {
32
+ this.addEventListeners();
33
+ };
34
+ // 增加节点拖拽和锚点拖拽的事件监听
35
+ ProximityConnect.prototype.addEventListeners = function () {
36
+ var _this = this;
37
+ // 节点开始拖拽事件
38
+ this.lf.graphModel.eventCenter.on('node:dragstart', function (_a) {
39
+ var data = _a.data;
40
+ if (!_this.enable)
41
+ return;
42
+ var graphModel = _this.lf.graphModel;
43
+ var id = data.id;
44
+ _this.currentNode = graphModel.getNodeModelById(id);
45
+ });
46
+ // 节点拖拽事件
47
+ this.lf.graphModel.eventCenter.on('node:drag', function () {
48
+ _this.handleNodeDrag();
49
+ });
50
+ // 锚点开始拖拽事件
51
+ this.lf.graphModel.eventCenter.on('anchor:dragstart', function (_a) {
52
+ var data = _a.data, nodeModel = _a.nodeModel;
53
+ if (!_this.enable)
54
+ return;
55
+ _this.currentNode = nodeModel;
56
+ _this.currentAnchor = data;
57
+ });
58
+ // 锚点拖拽事件
59
+ this.lf.graphModel.eventCenter.on('anchor:drag', function (_a) {
60
+ var _b = _a.e, clientX = _b.clientX, clientY = _b.clientY;
61
+ if (!_this.enable)
62
+ return;
63
+ _this.handleAnchorDrag(clientX, clientY);
64
+ });
65
+ // 节点、锚点拖拽结束事件
66
+ this.lf.graphModel.eventCenter.on('node:drop,anchor:dragend', function () {
67
+ if (!_this.enable)
68
+ return;
69
+ _this.handleDrop();
70
+ });
71
+ };
72
+ // 节点拖拽动作
73
+ ProximityConnect.prototype.handleNodeDrag = function () {
74
+ /**
75
+ * 主要做几件事情
76
+ * 判断当前是否有虚拟连线,有的话判断两点距离是否超过阈值,超过的话删除连线
77
+ * 遍历画布上的所有节点,找到距离最近的节点,获取其所有锚点数据
78
+ * 判断每个锚点与当前选中节点的所有锚点之间的距离,找到路路径最短的两个点时,把当前节点、当前锚点当前最短记录记录下来,作为当前最近数据
79
+ * 判断当前最短距离是否小于阈值
80
+ * 如果是 就创建虚拟边
81
+ */
82
+ var nodes = this.lf.graphModel.nodes;
83
+ if (!(0, lodash_es_1.isNil)(this.virtualEdge)) {
84
+ var _a = this.virtualEdge, startPoint = _a.startPoint, endPoint = _a.endPoint, id = _a.id;
85
+ var curDistance = (0, core_1.twoPointDistance)(startPoint, endPoint);
86
+ if (curDistance > this.thresholdDistance) {
87
+ this.lf.deleteEdge(id);
88
+ this.virtualEdge = undefined;
89
+ }
90
+ }
91
+ if (this.currentNode) {
92
+ this.findClosestAnchorOfNode(this.currentNode, nodes);
93
+ }
94
+ if (this.currentDistance < this.thresholdDistance) {
95
+ this.addVirtualEdge();
96
+ }
97
+ };
98
+ // 节点放下
99
+ ProximityConnect.prototype.handleDrop = function () {
100
+ this.addActualEdge();
101
+ this.resetData();
102
+ };
103
+ // 锚点拖拽动作
104
+ ProximityConnect.prototype.handleAnchorDrag = function (clientX, clientY) {
105
+ // 获取当前点在画布上的位置
106
+ var graphModel = this.lf.graphModel;
107
+ var _a = graphModel.getPointByClient({
108
+ x: clientX,
109
+ y: clientY,
110
+ }).canvasOverlayPosition, x = _a.x, y = _a.y;
111
+ if ((0, lodash_es_1.isNil)(x) || (0, lodash_es_1.isNil)(y))
112
+ return;
113
+ var currentPoint = { x: x, y: y };
114
+ var nodes = graphModel.nodes;
115
+ // 判断当前是否有虚拟连线,有的话判断两点距离是否超过阈值,超过的话删除连线
116
+ if (!(0, lodash_es_1.isNil)(this.virtualEdge)) {
117
+ var _b = this.virtualEdge, endPoint = _b.endPoint, id = _b.id;
118
+ var curDistance = (0, core_1.twoPointDistance)(currentPoint, endPoint);
119
+ if (curDistance > this.thresholdDistance) {
120
+ this.lf.deleteEdge(id);
121
+ this.virtualEdge = undefined;
122
+ }
123
+ }
124
+ // 记录最近点的信息
125
+ this.findClosestAnchorOfAnchor(currentPoint, nodes);
126
+ if (this.currentDistance < this.thresholdDistance) {
127
+ this.addVirtualEdge();
128
+ }
129
+ };
130
+ // 节点→节点 找最近的节点和锚点
131
+ ProximityConnect.prototype.findClosestAnchorOfNode = function (draggingNode, allNodes) {
132
+ var _this = this;
133
+ if ((0, lodash_es_1.isNil)(draggingNode) || (0, lodash_es_1.isEmpty)(draggingNode))
134
+ return;
135
+ var _a = draggingNode.anchors, draggingAnchors = _a === void 0 ? [] : _a, id = draggingNode.id;
136
+ var distance;
137
+ var preConnectAnchor;
138
+ var closestAnchor;
139
+ var closestNode;
140
+ allNodes.forEach(function (node) {
141
+ if ((0, lodash_es_1.isEqual)(node.id, id))
142
+ return;
143
+ var _a = node.anchors, anchors = _a === void 0 ? [] : _a;
144
+ // 遍历所有节点,找离当前拖拽节点最近的可连接节点和锚点
145
+ anchors.forEach(function (anchor) {
146
+ // 找距离最近的两个锚点
147
+ draggingAnchors.forEach(function (draggingAnchor) {
148
+ // 判断拖拽点锚点和当前锚点是否可连线
149
+ var anchorAllowConnect = _this.anchorAllowConnect(node, anchor, draggingAnchor);
150
+ if (!anchorAllowConnect)
151
+ return;
152
+ // 获取两个锚点之间的距离
153
+ var curDistance = (0, core_1.twoPointDistance)(draggingAnchor, anchor);
154
+ if (!distance || curDistance < distance) {
155
+ // 如果是第一条数据,或者当前这对锚点距离更短,就替换数据
156
+ distance = curDistance;
157
+ preConnectAnchor = draggingAnchor;
158
+ closestAnchor = anchor;
159
+ closestNode = node;
160
+ }
161
+ });
162
+ });
163
+ });
164
+ this.currentDistance = distance;
165
+ this.currentAnchor = preConnectAnchor;
166
+ this.closestAnchor = closestAnchor;
167
+ this.closestNode = closestNode;
168
+ };
169
+ // 锚点→节点 找最近的锚点
170
+ ProximityConnect.prototype.findClosestAnchorOfAnchor = function (draggingPoint, allNodes) {
171
+ var _this = this;
172
+ if ((0, lodash_es_1.isNil)(draggingPoint))
173
+ return;
174
+ var distance;
175
+ var closestAnchor;
176
+ var closestNode;
177
+ var _a = this, currentNode = _a.currentNode, currentAnchor = _a.currentAnchor;
178
+ allNodes.forEach(function (node) {
179
+ if (!currentNode)
180
+ return;
181
+ var _a = node.anchors, anchors = _a === void 0 ? [] : _a;
182
+ // 遍历所有节点,找离当前拖拽节点最近的可连接节点和锚点
183
+ anchors.forEach(function (anchor) {
184
+ var _a;
185
+ if ((0, lodash_es_1.isEqual)((_a = _this.currentAnchor) === null || _a === void 0 ? void 0 : _a.id, anchor.id))
186
+ return;
187
+ // 判断拖拽点锚点和当前锚点是否可连线
188
+ var anchorAllowConnect = _this.anchorAllowConnect(node, anchor, currentAnchor);
189
+ if (!anchorAllowConnect)
190
+ return;
191
+ // 获取两个锚点之间的距离
192
+ var curDistance = (0, core_1.twoPointDistance)(draggingPoint, anchor);
193
+ if (!distance || curDistance < distance) {
194
+ // 如果是第一条数据,或者当前这对锚点距离更短,就替换数据
195
+ distance = curDistance;
196
+ closestAnchor = anchor;
197
+ closestNode = node;
198
+ }
199
+ });
200
+ });
201
+ this.currentDistance = distance;
202
+ this.closestAnchor = closestAnchor;
203
+ this.closestNode = closestNode;
204
+ };
205
+ // 判断锚点是否允许连线
206
+ ProximityConnect.prototype.anchorAllowConnect = function (node, anchor, draggingAnchor) {
207
+ var currentNode = this.currentNode;
208
+ if (!currentNode)
209
+ return;
210
+ // 判断起点是否可连接
211
+ var sourceValidResult = (this.reverseDirection
212
+ ? node.isAllowConnectedAsSource(currentNode, anchor, draggingAnchor)
213
+ : currentNode.isAllowConnectedAsSource(node, draggingAnchor, anchor)).isAllPass;
214
+ // 判断终点是否可连接
215
+ var targetValidResult = (this.reverseDirection
216
+ ? currentNode.isAllowConnectedAsTarget(node, anchor, draggingAnchor)
217
+ : node.isAllowConnectedAsTarget(currentNode, draggingAnchor, anchor)).isAllPass;
218
+ return sourceValidResult && targetValidResult;
219
+ };
220
+ // 判断是否应该删除虚拟边
221
+ ProximityConnect.prototype.sameEdgeIsExist = function (edge) {
222
+ if ((0, lodash_es_1.isNil)(this.closestNode) ||
223
+ (0, lodash_es_1.isNil)(this.currentNode) ||
224
+ (0, lodash_es_1.isNil)(this.closestAnchor) ||
225
+ (0, lodash_es_1.isNil)(this.currentAnchor))
226
+ return false;
227
+ if ((0, lodash_es_1.isNil)(edge))
228
+ return false;
229
+ var _a = this, closestNodeId = _a.closestNode.id, currentNodeId = _a.currentNode.id, closestAnchorId = _a.closestAnchor.id, currentAnchorId = _a.currentAnchor.id, reverseDirection = _a.reverseDirection;
230
+ var sourceNodeId = edge.sourceNodeId, targetNodeId = edge.targetNodeId, sourceAnchorId = edge.sourceAnchorId, targetAnchorId = edge.targetAnchorId;
231
+ var isExist = reverseDirection
232
+ ? (0, lodash_es_1.isEqual)(closestNodeId, sourceNodeId) &&
233
+ (0, lodash_es_1.isEqual)(currentNodeId, targetNodeId) &&
234
+ (0, lodash_es_1.isEqual)(closestAnchorId, sourceAnchorId) &&
235
+ (0, lodash_es_1.isEqual)(currentAnchorId, targetAnchorId)
236
+ : (0, lodash_es_1.isEqual)(currentNodeId, sourceNodeId) &&
237
+ (0, lodash_es_1.isEqual)(closestNodeId, targetNodeId) &&
238
+ (0, lodash_es_1.isEqual)(currentAnchorId, sourceAnchorId) &&
239
+ (0, lodash_es_1.isEqual)(closestAnchorId, targetAnchorId);
240
+ return isExist;
241
+ };
242
+ // 增加虚拟边
243
+ ProximityConnect.prototype.addVirtualEdge = function () {
244
+ var _this = this;
245
+ var edges = this.lf.graphModel.edges;
246
+ // 判断当前是否已存在一条同样配置的真实边
247
+ var actualEdgeIsExist = (0, lodash_es_1.reduce)(edges, function (result, edge) {
248
+ if (edge.virtual)
249
+ return result;
250
+ return result || _this.sameEdgeIsExist(edge);
251
+ }, false);
252
+ // 如果有真实边就不重复创建边了
253
+ if (actualEdgeIsExist)
254
+ return;
255
+ // 判断当前是否有虚拟边
256
+ // 如果当前已有虚拟边,判断当前的节点和锚点信息与虚拟边的信息是否一致
257
+ if (!(0, lodash_es_1.isNil)(this.virtualEdge)) {
258
+ var edgeId = this.virtualEdge.id;
259
+ // 信息一致不做处理
260
+ if (this.sameEdgeIsExist(this.virtualEdge))
261
+ return;
262
+ // 不一致就删除老边
263
+ this.lf.deleteEdge(edgeId);
264
+ }
265
+ // 开始创建虚拟边
266
+ var _a = this, reverseDirection = _a.reverseDirection, currentNode = _a.currentNode, closestNode = _a.closestNode, currentAnchor = _a.currentAnchor, closestAnchor = _a.closestAnchor;
267
+ if ((0, lodash_es_1.isEmpty)(currentNode) || (0, lodash_es_1.isEmpty)(closestNode))
268
+ return;
269
+ var properties = {
270
+ style: this.virtualEdgeStyle,
271
+ };
272
+ this.virtualEdge = this.lf.addEdge(reverseDirection
273
+ ? {
274
+ sourceNodeId: closestNode === null || closestNode === void 0 ? void 0 : closestNode.id,
275
+ targetNodeId: currentNode === null || currentNode === void 0 ? void 0 : currentNode.id,
276
+ sourceAnchorId: closestAnchor === null || closestAnchor === void 0 ? void 0 : closestAnchor.id,
277
+ targetAnchorId: currentAnchor === null || currentAnchor === void 0 ? void 0 : currentAnchor.id,
278
+ properties: properties,
279
+ }
280
+ : {
281
+ sourceNodeId: currentNode === null || currentNode === void 0 ? void 0 : currentNode.id,
282
+ targetNodeId: closestNode === null || closestNode === void 0 ? void 0 : closestNode.id,
283
+ sourceAnchorId: currentAnchor === null || currentAnchor === void 0 ? void 0 : currentAnchor.id,
284
+ targetAnchorId: closestAnchor === null || closestAnchor === void 0 ? void 0 : closestAnchor.id,
285
+ properties: properties,
286
+ });
287
+ this.virtualEdge.virtual = true;
288
+ };
289
+ // 增加实体边
290
+ ProximityConnect.prototype.addActualEdge = function () {
291
+ if ((0, lodash_es_1.isNil)(this.virtualEdge))
292
+ return;
293
+ var _a = this.virtualEdge, type = _a.type, sourceNodeId = _a.sourceNodeId, targetNodeId = _a.targetNodeId, sourceAnchorId = _a.sourceAnchorId, targetAnchorId = _a.targetAnchorId, startPoint = _a.startPoint, endPoint = _a.endPoint, pointsList = _a.pointsList;
294
+ this.lf.addEdge({
295
+ type: type,
296
+ sourceNodeId: sourceNodeId,
297
+ targetNodeId: targetNodeId,
298
+ sourceAnchorId: sourceAnchorId,
299
+ targetAnchorId: targetAnchorId,
300
+ startPoint: startPoint,
301
+ endPoint: endPoint,
302
+ pointsList: pointsList,
303
+ });
304
+ this.lf.deleteEdge(this.virtualEdge.id);
305
+ };
306
+ // 设置虚拟边样式
307
+ ProximityConnect.prototype.setVirtualEdgeStyle = function (value) {
308
+ this.virtualEdgeStyle = __assign(__assign({}, this.virtualEdgeStyle), value);
309
+ };
310
+ // 设置连线阈值
311
+ ProximityConnect.prototype.setThresholdDistance = function (distance) {
312
+ console.log('distance', distance);
313
+ if (!(0, lodash_es_1.isFinite)(distance))
314
+ return;
315
+ this.thresholdDistance = distance;
316
+ };
317
+ // 设置连线方向
318
+ ProximityConnect.prototype.setReverseDirection = function (value) {
319
+ this.reverseDirection = value;
320
+ };
321
+ // 设置插件开关状态
322
+ ProximityConnect.prototype.setEnable = function (enable) {
323
+ this.enable = enable;
324
+ if (!enable) {
325
+ this.resetData();
326
+ }
327
+ };
328
+ // 重置数据
329
+ ProximityConnect.prototype.resetData = function () {
330
+ this.closestNode = undefined;
331
+ this.currentDistance = Infinity;
332
+ this.currentNode = undefined;
333
+ this.currentAnchor = undefined;
334
+ this.closestAnchor = undefined;
335
+ this.virtualEdge = undefined;
336
+ };
337
+ ProximityConnect.pluginName = 'proximityConnect';
338
+ return ProximityConnect;
339
+ }());
340
+ exports.ProximityConnect = ProximityConnect;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logicflow/extension",
3
- "version": "2.0.11",
3
+ "version": "2.0.13",
4
4
  "description": "LogicFlow Extensions",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -20,7 +20,7 @@
20
20
  "author": "Logicflow-Team",
21
21
  "license": "Apache-2.0",
22
22
  "peerDependencies": {
23
- "@logicflow/core": "2.0.7"
23
+ "@logicflow/core": "2.0.9"
24
24
  },
25
25
  "dependencies": {
26
26
  "@antv/hierarchy": "^0.6.11",
@@ -31,7 +31,7 @@
31
31
  "preact": "^10.17.1",
32
32
  "rangy": "^1.3.1",
33
33
  "vanilla-picker": "^2.12.3",
34
- "@logicflow/core": "2.0.7"
34
+ "@logicflow/core": "2.0.9"
35
35
  },
36
36
  "devDependencies": {
37
37
  "less": "^4.1.1",