@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.
- package/.turbo/turbo-build.log +34 -34
- package/CHANGELOG.md +23 -1
- package/dist/index.css +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/components/mini-map/index.d.ts +2 -0
- package/es/components/mini-map/index.js +10 -0
- package/es/dynamic-group/index.d.ts +2 -1
- package/es/dynamic-group/index.js +21 -19
- package/es/index.css +1 -1
- package/es/index.d.ts +1 -0
- package/es/index.js +1 -0
- package/es/materials/group/GroupNode.d.ts +5 -5
- package/es/materials/group/GroupNode.js +3 -3
- package/es/materials/group/index.js +5 -5
- package/es/materials/node-selection/index.d.ts +6 -6
- package/es/materials/node-selection/index.js +90 -10
- package/es/style/index.css +1 -1
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/tools/label/Label.d.ts +4 -0
- package/es/tools/label/Label.js +75 -31
- package/es/tools/label/LabelModel.js +1 -0
- package/es/tools/label/index.d.ts +1 -0
- package/es/tools/label/index.js +47 -3
- package/es/tools/proximity-connect/index.d.ts +42 -0
- package/es/tools/proximity-connect/index.js +337 -0
- package/lib/components/mini-map/index.d.ts +2 -0
- package/lib/components/mini-map/index.js +10 -0
- package/lib/dynamic-group/index.d.ts +2 -1
- package/lib/dynamic-group/index.js +21 -19
- package/lib/index.css +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/materials/group/GroupNode.d.ts +5 -5
- package/lib/materials/group/GroupNode.js +3 -3
- package/lib/materials/group/index.js +5 -5
- package/lib/materials/node-selection/index.d.ts +6 -6
- package/lib/materials/node-selection/index.js +89 -9
- package/lib/style/index.css +1 -1
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/tools/label/Label.d.ts +4 -0
- package/lib/tools/label/Label.js +75 -31
- package/lib/tools/label/LabelModel.js +1 -0
- package/lib/tools/label/index.d.ts +1 -0
- package/lib/tools/label/index.js +46 -2
- package/lib/tools/proximity-connect/index.d.ts +42 -0
- package/lib/tools/proximity-connect/index.js +340 -0
- package/package.json +3 -3
- package/src/components/mini-map/index.ts +11 -0
- package/src/dynamic-group/index.ts +29 -8
- package/src/index.ts +1 -0
- package/src/materials/group/GroupNode.ts +3 -3
- package/src/materials/group/index.ts +5 -5
- package/src/materials/node-selection/index.ts +115 -14
- package/src/style/index.less +3 -5
- package/src/style/raw.ts +3 -7
- package/src/tools/label/Label.tsx +106 -55
- package/src/tools/label/LabelModel.ts +1 -0
- package/src/tools/label/index.ts +64 -3
- package/src/tools/proximity-connect/index.ts +399 -0
- package/stats.html +1 -1
package/src/tools/label/index.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import LogicFlow, { createUuid, GraphModel, TextMode } from '@logicflow/core'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
cloneDeep,
|
|
4
|
+
forEach,
|
|
5
|
+
isArray,
|
|
6
|
+
isEmpty,
|
|
7
|
+
isEqual,
|
|
8
|
+
isObject,
|
|
9
|
+
map,
|
|
10
|
+
} from 'lodash-es'
|
|
3
11
|
import LabelOverlay, { LabelConfigType } from './LabelOverlay'
|
|
4
12
|
import {
|
|
5
13
|
BBoxInfo,
|
|
@@ -53,7 +61,7 @@ export class Label implements Extension {
|
|
|
53
61
|
this.addEventListeners()
|
|
54
62
|
|
|
55
63
|
// TODO: 3. 自定义快捷键,比如 delete,选中 label 时,移除 label
|
|
56
|
-
|
|
64
|
+
this.rewriteShortcut()
|
|
57
65
|
|
|
58
66
|
// 插件中注册 LabelOverlay 工具,用于 label 的编辑
|
|
59
67
|
lf.tool.registerTool(LabelOverlay.toolName, LabelOverlay)
|
|
@@ -377,7 +385,60 @@ export class Label implements Extension {
|
|
|
377
385
|
// TODO: others methods ???
|
|
378
386
|
}
|
|
379
387
|
|
|
380
|
-
|
|
388
|
+
private rewriteShortcut() {
|
|
389
|
+
const { keyboard, graphModel } = this.lf
|
|
390
|
+
const {
|
|
391
|
+
options: { keyboard: keyboardOptions },
|
|
392
|
+
} = keyboard
|
|
393
|
+
keyboard.off(['backspace'])
|
|
394
|
+
keyboard.on(['backspace'], () => {
|
|
395
|
+
if (!keyboardOptions?.enabled) return true
|
|
396
|
+
if (graphModel.textEditElement) return true
|
|
397
|
+
const elements = graphModel.getSelectElements(true)
|
|
398
|
+
this.lf.clearSelectElements()
|
|
399
|
+
const {
|
|
400
|
+
graphModel: { editConfigModel },
|
|
401
|
+
} = this.lf
|
|
402
|
+
elements.edges.forEach((edge) => {
|
|
403
|
+
const { properties } = edge
|
|
404
|
+
if (
|
|
405
|
+
properties &&
|
|
406
|
+
!isEmpty(properties._label) &&
|
|
407
|
+
editConfigModel.textMode === TextMode.LABEL
|
|
408
|
+
) {
|
|
409
|
+
const newLabelList = properties._label.filter(
|
|
410
|
+
(label) => !label.isSelected,
|
|
411
|
+
)
|
|
412
|
+
// 如果两个labelList长度不一致,说明有选中的元素,此时backspace做的动作是删除label
|
|
413
|
+
if (!isEqual(newLabelList.length, properties._label.length)) {
|
|
414
|
+
const edgeModel = graphModel.getEdgeModelById(edge.id)
|
|
415
|
+
edgeModel?.setProperty('_label', newLabelList)
|
|
416
|
+
return
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
edge.id && this.lf.deleteEdge(edge.id)
|
|
420
|
+
})
|
|
421
|
+
elements.nodes.forEach((node) => {
|
|
422
|
+
const { properties } = node
|
|
423
|
+
if (
|
|
424
|
+
properties &&
|
|
425
|
+
!isEmpty(properties._label) &&
|
|
426
|
+
editConfigModel.textMode === TextMode.LABEL
|
|
427
|
+
) {
|
|
428
|
+
const newLabelList = properties._label.filter(
|
|
429
|
+
(label) => !label.isSelected,
|
|
430
|
+
)
|
|
431
|
+
if (!isEqual(newLabelList.length, properties._label.length)) {
|
|
432
|
+
const nodeModel = graphModel.getNodeModelById(node.id)
|
|
433
|
+
nodeModel?.setProperty('_label', newLabelList)
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
node.id && this.lf.deleteNode(node.id)
|
|
438
|
+
})
|
|
439
|
+
return false
|
|
440
|
+
})
|
|
441
|
+
}
|
|
381
442
|
|
|
382
443
|
/**
|
|
383
444
|
* 更新当前渲染使用的 Text or Label 模式
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import LogicFlow, {
|
|
2
|
+
Model,
|
|
3
|
+
twoPointDistance,
|
|
4
|
+
BaseNodeModel,
|
|
5
|
+
BaseEdgeModel,
|
|
6
|
+
} from '@logicflow/core'
|
|
7
|
+
import { assign, isEmpty, isEqual, isNil, isFinite, reduce } from 'lodash-es'
|
|
8
|
+
|
|
9
|
+
import AnchorConfig = Model.AnchorConfig
|
|
10
|
+
import Point = LogicFlow.Point
|
|
11
|
+
|
|
12
|
+
export type ProximityConnectProps = {
|
|
13
|
+
enable: boolean
|
|
14
|
+
distance: number
|
|
15
|
+
reverseDirection: boolean
|
|
16
|
+
virtualEdgeStyle: Record<string, unknown>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class ProximityConnect {
|
|
20
|
+
static pluginName = 'proximityConnect'
|
|
21
|
+
enable: boolean = true
|
|
22
|
+
lf: LogicFlow // lf实例
|
|
23
|
+
closestNode?: BaseNodeModel // 当前距离最近的节点
|
|
24
|
+
currentDistance: number = Infinity // 当前间距
|
|
25
|
+
thresholdDistance: number = 100 // 节点-节点连接距离阈值
|
|
26
|
+
|
|
27
|
+
currentNode?: BaseNodeModel // 当前操作节点
|
|
28
|
+
reverseDirection: boolean = false // 节点-节点连线方向,默认是拖拽节点连向最近节点
|
|
29
|
+
|
|
30
|
+
currentAnchor?: AnchorConfig // 当前连线锚点
|
|
31
|
+
closestAnchor?: AnchorConfig // 当前距离最近锚点
|
|
32
|
+
virtualEdge?: BaseEdgeModel // 虚拟边
|
|
33
|
+
virtualEdgeStyle: Record<string, unknown> = {
|
|
34
|
+
strokeDasharray: '10,10',
|
|
35
|
+
stroke: '#acacac',
|
|
36
|
+
} // 虚拟边样式
|
|
37
|
+
|
|
38
|
+
constructor({
|
|
39
|
+
lf,
|
|
40
|
+
options,
|
|
41
|
+
}: LogicFlow.IExtensionProps & { options: ProximityConnectProps }) {
|
|
42
|
+
this.lf = lf
|
|
43
|
+
assign(this, options)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
render() {
|
|
47
|
+
this.addEventListeners()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 增加节点拖拽和锚点拖拽的事件监听
|
|
51
|
+
addEventListeners() {
|
|
52
|
+
// 节点开始拖拽事件
|
|
53
|
+
this.lf.graphModel.eventCenter.on('node:dragstart', ({ data }) => {
|
|
54
|
+
if (!this.enable) return
|
|
55
|
+
const { graphModel } = this.lf
|
|
56
|
+
const { id } = data
|
|
57
|
+
this.currentNode = graphModel.getNodeModelById(id)
|
|
58
|
+
})
|
|
59
|
+
// 节点拖拽事件
|
|
60
|
+
this.lf.graphModel.eventCenter.on('node:drag', () => {
|
|
61
|
+
this.handleNodeDrag()
|
|
62
|
+
})
|
|
63
|
+
// 锚点开始拖拽事件
|
|
64
|
+
this.lf.graphModel.eventCenter.on(
|
|
65
|
+
'anchor:dragstart',
|
|
66
|
+
({ data, nodeModel }) => {
|
|
67
|
+
if (!this.enable) return
|
|
68
|
+
this.currentNode = nodeModel
|
|
69
|
+
this.currentAnchor = data
|
|
70
|
+
},
|
|
71
|
+
)
|
|
72
|
+
// 锚点拖拽事件
|
|
73
|
+
this.lf.graphModel.eventCenter.on(
|
|
74
|
+
'anchor:drag',
|
|
75
|
+
({ e: { clientX, clientY } }) => {
|
|
76
|
+
if (!this.enable) return
|
|
77
|
+
this.handleAnchorDrag(clientX, clientY)
|
|
78
|
+
},
|
|
79
|
+
)
|
|
80
|
+
// 节点、锚点拖拽结束事件
|
|
81
|
+
this.lf.graphModel.eventCenter.on('node:drop,anchor:dragend', () => {
|
|
82
|
+
if (!this.enable) return
|
|
83
|
+
this.handleDrop()
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 节点拖拽动作
|
|
88
|
+
handleNodeDrag() {
|
|
89
|
+
/**
|
|
90
|
+
* 主要做几件事情
|
|
91
|
+
* 判断当前是否有虚拟连线,有的话判断两点距离是否超过阈值,超过的话删除连线
|
|
92
|
+
* 遍历画布上的所有节点,找到距离最近的节点,获取其所有锚点数据
|
|
93
|
+
* 判断每个锚点与当前选中节点的所有锚点之间的距离,找到路路径最短的两个点时,把当前节点、当前锚点当前最短记录记录下来,作为当前最近数据
|
|
94
|
+
* 判断当前最短距离是否小于阈值
|
|
95
|
+
* 如果是 就创建虚拟边
|
|
96
|
+
*/
|
|
97
|
+
const { nodes } = this.lf.graphModel
|
|
98
|
+
|
|
99
|
+
if (!isNil(this.virtualEdge)) {
|
|
100
|
+
const { startPoint, endPoint, id } = this.virtualEdge
|
|
101
|
+
const curDistance = twoPointDistance(startPoint, endPoint)
|
|
102
|
+
if (curDistance > this.thresholdDistance) {
|
|
103
|
+
this.lf.deleteEdge(id)
|
|
104
|
+
this.virtualEdge = undefined
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (this.currentNode) {
|
|
108
|
+
this.findClosestAnchorOfNode(this.currentNode, nodes)
|
|
109
|
+
}
|
|
110
|
+
if (this.currentDistance < this.thresholdDistance) {
|
|
111
|
+
this.addVirtualEdge()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 节点放下
|
|
116
|
+
handleDrop() {
|
|
117
|
+
this.addActualEdge()
|
|
118
|
+
this.resetData()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 锚点拖拽动作
|
|
122
|
+
handleAnchorDrag(clientX: number, clientY: number) {
|
|
123
|
+
// 获取当前点在画布上的位置
|
|
124
|
+
const { graphModel } = this.lf
|
|
125
|
+
const {
|
|
126
|
+
canvasOverlayPosition: { x, y },
|
|
127
|
+
} = graphModel.getPointByClient({
|
|
128
|
+
x: clientX,
|
|
129
|
+
y: clientY,
|
|
130
|
+
})
|
|
131
|
+
if (isNil(x) || isNil(y)) return
|
|
132
|
+
const currentPoint: Point = { x, y }
|
|
133
|
+
const { nodes } = graphModel
|
|
134
|
+
// 判断当前是否有虚拟连线,有的话判断两点距离是否超过阈值,超过的话删除连线
|
|
135
|
+
if (!isNil(this.virtualEdge)) {
|
|
136
|
+
const { endPoint, id } = this.virtualEdge
|
|
137
|
+
const curDistance = twoPointDistance(currentPoint, endPoint)
|
|
138
|
+
if (curDistance > this.thresholdDistance) {
|
|
139
|
+
this.lf.deleteEdge(id)
|
|
140
|
+
this.virtualEdge = undefined
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// 记录最近点的信息
|
|
144
|
+
this.findClosestAnchorOfAnchor(currentPoint, nodes)
|
|
145
|
+
if (this.currentDistance < this.thresholdDistance) {
|
|
146
|
+
this.addVirtualEdge()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 节点→节点 找最近的节点和锚点
|
|
151
|
+
findClosestAnchorOfNode(
|
|
152
|
+
draggingNode: BaseNodeModel,
|
|
153
|
+
allNodes: BaseNodeModel[],
|
|
154
|
+
) {
|
|
155
|
+
if (isNil(draggingNode) || isEmpty(draggingNode)) return
|
|
156
|
+
const { anchors: draggingAnchors = [], id } = draggingNode
|
|
157
|
+
let distance
|
|
158
|
+
let preConnectAnchor
|
|
159
|
+
let closestAnchor
|
|
160
|
+
let closestNode
|
|
161
|
+
allNodes.forEach((node) => {
|
|
162
|
+
if (isEqual(node.id, id)) return
|
|
163
|
+
const { anchors = [] } = node
|
|
164
|
+
// 遍历所有节点,找离当前拖拽节点最近的可连接节点和锚点
|
|
165
|
+
anchors.forEach((anchor) => {
|
|
166
|
+
// 找距离最近的两个锚点
|
|
167
|
+
draggingAnchors.forEach((draggingAnchor) => {
|
|
168
|
+
// 判断拖拽点锚点和当前锚点是否可连线
|
|
169
|
+
const anchorAllowConnect = this.anchorAllowConnect(
|
|
170
|
+
node,
|
|
171
|
+
anchor,
|
|
172
|
+
draggingAnchor,
|
|
173
|
+
)
|
|
174
|
+
if (!anchorAllowConnect) return
|
|
175
|
+
// 获取两个锚点之间的距离
|
|
176
|
+
const curDistance = twoPointDistance(draggingAnchor, anchor)
|
|
177
|
+
if (!distance || curDistance < distance) {
|
|
178
|
+
// 如果是第一条数据,或者当前这对锚点距离更短,就替换数据
|
|
179
|
+
distance = curDistance
|
|
180
|
+
preConnectAnchor = draggingAnchor
|
|
181
|
+
closestAnchor = anchor
|
|
182
|
+
closestNode = node
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
this.currentDistance = distance
|
|
188
|
+
this.currentAnchor = preConnectAnchor
|
|
189
|
+
this.closestAnchor = closestAnchor
|
|
190
|
+
this.closestNode = closestNode
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 锚点→节点 找最近的锚点
|
|
194
|
+
findClosestAnchorOfAnchor(draggingPoint: Point, allNodes: BaseNodeModel[]) {
|
|
195
|
+
if (isNil(draggingPoint)) return
|
|
196
|
+
let distance
|
|
197
|
+
let closestAnchor
|
|
198
|
+
let closestNode
|
|
199
|
+
const { currentNode, currentAnchor } = this
|
|
200
|
+
allNodes.forEach((node) => {
|
|
201
|
+
if (!currentNode) return
|
|
202
|
+
const { anchors = [] } = node
|
|
203
|
+
// 遍历所有节点,找离当前拖拽节点最近的可连接节点和锚点
|
|
204
|
+
anchors.forEach((anchor) => {
|
|
205
|
+
if (isEqual(this.currentAnchor?.id, anchor.id)) return
|
|
206
|
+
// 判断拖拽点锚点和当前锚点是否可连线
|
|
207
|
+
const anchorAllowConnect = this.anchorAllowConnect(
|
|
208
|
+
node,
|
|
209
|
+
anchor,
|
|
210
|
+
currentAnchor,
|
|
211
|
+
)
|
|
212
|
+
if (!anchorAllowConnect) return
|
|
213
|
+
// 获取两个锚点之间的距离
|
|
214
|
+
const curDistance = twoPointDistance(draggingPoint, anchor)
|
|
215
|
+
if (!distance || curDistance < distance) {
|
|
216
|
+
// 如果是第一条数据,或者当前这对锚点距离更短,就替换数据
|
|
217
|
+
distance = curDistance
|
|
218
|
+
closestAnchor = anchor
|
|
219
|
+
closestNode = node
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
this.currentDistance = distance
|
|
224
|
+
this.closestAnchor = closestAnchor
|
|
225
|
+
this.closestNode = closestNode
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 判断锚点是否允许连线
|
|
229
|
+
anchorAllowConnect(
|
|
230
|
+
node: BaseNodeModel,
|
|
231
|
+
anchor: AnchorConfig,
|
|
232
|
+
draggingAnchor: AnchorConfig | undefined,
|
|
233
|
+
) {
|
|
234
|
+
const { currentNode } = this
|
|
235
|
+
if (!currentNode) return
|
|
236
|
+
// 判断起点是否可连接
|
|
237
|
+
const { isAllPass: sourceValidResult } = this.reverseDirection
|
|
238
|
+
? node.isAllowConnectedAsSource(currentNode, anchor, draggingAnchor)
|
|
239
|
+
: currentNode.isAllowConnectedAsSource(node, draggingAnchor, anchor)
|
|
240
|
+
// 判断终点是否可连接
|
|
241
|
+
const { isAllPass: targetValidResult } = this.reverseDirection
|
|
242
|
+
? currentNode.isAllowConnectedAsTarget(node, anchor, draggingAnchor)
|
|
243
|
+
: node.isAllowConnectedAsTarget(currentNode, draggingAnchor, anchor)
|
|
244
|
+
return sourceValidResult && targetValidResult
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 判断是否应该删除虚拟边
|
|
248
|
+
sameEdgeIsExist(edge: BaseEdgeModel) {
|
|
249
|
+
if (
|
|
250
|
+
isNil(this.closestNode) ||
|
|
251
|
+
isNil(this.currentNode) ||
|
|
252
|
+
isNil(this.closestAnchor) ||
|
|
253
|
+
isNil(this.currentAnchor)
|
|
254
|
+
)
|
|
255
|
+
return false
|
|
256
|
+
if (isNil(edge)) return false
|
|
257
|
+
const {
|
|
258
|
+
closestNode: { id: closestNodeId },
|
|
259
|
+
currentNode: { id: currentNodeId },
|
|
260
|
+
closestAnchor: { id: closestAnchorId },
|
|
261
|
+
currentAnchor: { id: currentAnchorId },
|
|
262
|
+
reverseDirection,
|
|
263
|
+
} = this
|
|
264
|
+
const { sourceNodeId, targetNodeId, sourceAnchorId, targetAnchorId } = edge
|
|
265
|
+
const isExist = reverseDirection
|
|
266
|
+
? isEqual(closestNodeId, sourceNodeId) &&
|
|
267
|
+
isEqual(currentNodeId, targetNodeId) &&
|
|
268
|
+
isEqual(closestAnchorId, sourceAnchorId) &&
|
|
269
|
+
isEqual(currentAnchorId, targetAnchorId)
|
|
270
|
+
: isEqual(currentNodeId, sourceNodeId) &&
|
|
271
|
+
isEqual(closestNodeId, targetNodeId) &&
|
|
272
|
+
isEqual(currentAnchorId, sourceAnchorId) &&
|
|
273
|
+
isEqual(closestAnchorId, targetAnchorId)
|
|
274
|
+
return isExist
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 增加虚拟边
|
|
278
|
+
addVirtualEdge() {
|
|
279
|
+
const { edges } = this.lf.graphModel
|
|
280
|
+
// 判断当前是否已存在一条同样配置的真实边
|
|
281
|
+
const actualEdgeIsExist = reduce(
|
|
282
|
+
edges,
|
|
283
|
+
(result, edge) => {
|
|
284
|
+
if (edge.virtual) return result
|
|
285
|
+
return result || this.sameEdgeIsExist(edge)
|
|
286
|
+
},
|
|
287
|
+
false,
|
|
288
|
+
)
|
|
289
|
+
// 如果有真实边就不重复创建边了
|
|
290
|
+
if (actualEdgeIsExist) return
|
|
291
|
+
|
|
292
|
+
// 判断当前是否有虚拟边
|
|
293
|
+
// 如果当前已有虚拟边,判断当前的节点和锚点信息与虚拟边的信息是否一致
|
|
294
|
+
if (!isNil(this.virtualEdge)) {
|
|
295
|
+
const {
|
|
296
|
+
virtualEdge: { id: edgeId },
|
|
297
|
+
} = this
|
|
298
|
+
// 信息一致不做处理
|
|
299
|
+
if (this.sameEdgeIsExist(this.virtualEdge)) return
|
|
300
|
+
// 不一致就删除老边
|
|
301
|
+
this.lf.deleteEdge(edgeId)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// 开始创建虚拟边
|
|
305
|
+
const {
|
|
306
|
+
reverseDirection,
|
|
307
|
+
currentNode,
|
|
308
|
+
closestNode,
|
|
309
|
+
currentAnchor,
|
|
310
|
+
closestAnchor,
|
|
311
|
+
} = this
|
|
312
|
+
if (isEmpty(currentNode) || isEmpty(closestNode)) return
|
|
313
|
+
const properties = {
|
|
314
|
+
style: this.virtualEdgeStyle,
|
|
315
|
+
}
|
|
316
|
+
this.virtualEdge = this.lf.addEdge(
|
|
317
|
+
reverseDirection
|
|
318
|
+
? {
|
|
319
|
+
sourceNodeId: closestNode?.id,
|
|
320
|
+
targetNodeId: currentNode?.id,
|
|
321
|
+
sourceAnchorId: closestAnchor?.id,
|
|
322
|
+
targetAnchorId: currentAnchor?.id,
|
|
323
|
+
properties,
|
|
324
|
+
}
|
|
325
|
+
: {
|
|
326
|
+
sourceNodeId: currentNode?.id,
|
|
327
|
+
targetNodeId: closestNode?.id,
|
|
328
|
+
sourceAnchorId: currentAnchor?.id,
|
|
329
|
+
targetAnchorId: closestAnchor?.id,
|
|
330
|
+
properties,
|
|
331
|
+
},
|
|
332
|
+
)
|
|
333
|
+
this.virtualEdge.virtual = true
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// 增加实体边
|
|
337
|
+
addActualEdge() {
|
|
338
|
+
if (isNil(this.virtualEdge)) return
|
|
339
|
+
const {
|
|
340
|
+
type,
|
|
341
|
+
sourceNodeId,
|
|
342
|
+
targetNodeId,
|
|
343
|
+
sourceAnchorId,
|
|
344
|
+
targetAnchorId,
|
|
345
|
+
startPoint,
|
|
346
|
+
endPoint,
|
|
347
|
+
pointsList,
|
|
348
|
+
} = this.virtualEdge
|
|
349
|
+
this.lf.addEdge({
|
|
350
|
+
type,
|
|
351
|
+
sourceNodeId,
|
|
352
|
+
targetNodeId,
|
|
353
|
+
sourceAnchorId,
|
|
354
|
+
targetAnchorId,
|
|
355
|
+
startPoint,
|
|
356
|
+
endPoint,
|
|
357
|
+
pointsList,
|
|
358
|
+
})
|
|
359
|
+
this.lf.deleteEdge(this.virtualEdge.id)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// 设置虚拟边样式
|
|
363
|
+
public setVirtualEdgeStyle(value: Record<string, unknown>) {
|
|
364
|
+
this.virtualEdgeStyle = {
|
|
365
|
+
...this.virtualEdgeStyle,
|
|
366
|
+
...value,
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// 设置连线阈值
|
|
371
|
+
public setThresholdDistance(distance: number) {
|
|
372
|
+
console.log('distance', distance)
|
|
373
|
+
if (!isFinite(distance)) return
|
|
374
|
+
this.thresholdDistance = distance
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 设置连线方向
|
|
378
|
+
public setReverseDirection(value: boolean) {
|
|
379
|
+
this.reverseDirection = value
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// 设置插件开关状态
|
|
383
|
+
public setEnable(enable: boolean) {
|
|
384
|
+
this.enable = enable
|
|
385
|
+
if (!enable) {
|
|
386
|
+
this.resetData()
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// 重置数据
|
|
391
|
+
resetData() {
|
|
392
|
+
this.closestNode = undefined
|
|
393
|
+
this.currentDistance = Infinity
|
|
394
|
+
this.currentNode = undefined
|
|
395
|
+
this.currentAnchor = undefined
|
|
396
|
+
this.closestAnchor = undefined
|
|
397
|
+
this.virtualEdge = undefined
|
|
398
|
+
}
|
|
399
|
+
}
|