@logicflow/extension 2.2.0-alpha.7 → 2.2.1
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/README.md +16 -0
- package/package.json +10 -7
- package/.turbo/turbo-build.log +0 -38
- package/CHANGELOG.md +0 -1829
- package/__test__/bpmn-adapter.test.js +0 -227
- package/es/materials/curved-edge/__test__/curved-edge.test.d.ts +0 -1
- package/es/materials/curved-edge/__test__/curved-edge.test.js +0 -18
- package/jest.config.js +0 -198
- package/lib/materials/curved-edge/__test__/curved-edge.test.d.ts +0 -1
- package/lib/materials/curved-edge/__test__/curved-edge.test.js +0 -20
- package/rollup.config.js +0 -52
- package/src/NodeResize/BasicShape/Ellipse.tsx +0 -22
- package/src/NodeResize/BasicShape/Polygon.tsx +0 -24
- package/src/NodeResize/BasicShape/Rect.tsx +0 -44
- package/src/NodeResize/control/Control.tsx +0 -537
- package/src/NodeResize/control/ControlGroup.tsx +0 -76
- package/src/NodeResize/control/Util.ts +0 -206
- package/src/NodeResize/index.ts +0 -26
- package/src/NodeResize/node/DiamondResize.tsx +0 -149
- package/src/NodeResize/node/EllipseResize.tsx +0 -140
- package/src/NodeResize/node/HtmlResize.tsx +0 -125
- package/src/NodeResize/node/RectResize.tsx +0 -126
- package/src/NodeResize/node/index.ts +0 -4
- package/src/bpmn/constant.ts +0 -56
- package/src/bpmn/events/EndEvent.ts +0 -73
- package/src/bpmn/events/StartEvent.ts +0 -52
- package/src/bpmn/events/index.ts +0 -2
- package/src/bpmn/flow/SequenceFlow.ts +0 -25
- package/src/bpmn/flow/index.ts +0 -1
- package/src/bpmn/gateways/ExclusiveGateway.ts +0 -71
- package/src/bpmn/gateways/index.ts +0 -1
- package/src/bpmn/getBpmnId.ts +0 -31
- package/src/bpmn/index.ts +0 -60
- package/src/bpmn/tasks/ServiceTask.ts +0 -63
- package/src/bpmn/tasks/UserTask.ts +0 -64
- package/src/bpmn/tasks/index.ts +0 -2
- package/src/bpmn-adapter/bpmnIds.ts +0 -31
- package/src/bpmn-adapter/index.ts +0 -835
- package/src/bpmn-adapter/json2xml.ts +0 -127
- package/src/bpmn-adapter/xml2json.ts +0 -544
- package/src/bpmn-elements/README.md +0 -223
- package/src/bpmn-elements/__tests__/definition.test.js +0 -72
- package/src/bpmn-elements/index.d.ts +0 -26
- package/src/bpmn-elements/index.ts +0 -107
- package/src/bpmn-elements/presets/Event/EndEventFactory.ts +0 -114
- package/src/bpmn-elements/presets/Event/IntermediateCatchEvent.ts +0 -108
- package/src/bpmn-elements/presets/Event/IntermediateThrowEvent.ts +0 -109
- package/src/bpmn-elements/presets/Event/StartEventFactory.ts +0 -114
- package/src/bpmn-elements/presets/Event/boundaryEventFactory.ts +0 -117
- package/src/bpmn-elements/presets/Event/index.ts +0 -14
- package/src/bpmn-elements/presets/Flow/flow.d.ts +0 -6
- package/src/bpmn-elements/presets/Flow/index.ts +0 -8
- package/src/bpmn-elements/presets/Flow/manhattan.ts +0 -691
- package/src/bpmn-elements/presets/Flow/sequenceFlow.ts +0 -65
- package/src/bpmn-elements/presets/Gateway/gateway.ts +0 -107
- package/src/bpmn-elements/presets/Gateway/index.ts +0 -23
- package/src/bpmn-elements/presets/Pool/Lane.ts +0 -211
- package/src/bpmn-elements/presets/Pool/Pool.ts +0 -284
- package/src/bpmn-elements/presets/Pool/index.ts +0 -89
- package/src/bpmn-elements/presets/Task/index.ts +0 -122
- package/src/bpmn-elements/presets/Task/subProcess.ts +0 -189
- package/src/bpmn-elements/presets/Task/task.ts +0 -193
- package/src/bpmn-elements/presets/icons.ts +0 -155
- package/src/bpmn-elements/utils.ts +0 -52
- package/src/bpmn-elements-adapter/README.md +0 -293
- package/src/bpmn-elements-adapter/__tests__/adapter_in.test.js +0 -528
- package/src/bpmn-elements-adapter/__tests__/adapter_out.test.js +0 -569
- package/src/bpmn-elements-adapter/constant.ts +0 -76
- package/src/bpmn-elements-adapter/index.ts +0 -1134
- package/src/bpmn-elements-adapter/json2xml.ts +0 -105
- package/src/bpmn-elements-adapter/xml2json.ts +0 -542
- package/src/components/context-menu/index.ts +0 -253
- package/src/components/control/index.ts +0 -155
- package/src/components/dnd-panel/index.ts +0 -137
- package/src/components/highlight/index.ts +0 -227
- package/src/components/menu/index.ts +0 -748
- package/src/components/mini-map/index.ts +0 -686
- package/src/components/selection-select/index.ts +0 -387
- package/src/dynamic-group/index.ts +0 -774
- package/src/dynamic-group/model.ts +0 -580
- package/src/dynamic-group/node.ts +0 -288
- package/src/dynamic-group/utils.ts +0 -46
- package/src/index.less +0 -1
- package/src/index.ts +0 -47
- package/src/insert-node-in-polyline/edge.ts +0 -175
- package/src/insert-node-in-polyline/index.ts +0 -193
- package/src/materials/curved-edge/__test__/curved-edge.test.ts +0 -46
- package/src/materials/curved-edge/index.ts +0 -217
- package/src/materials/group/GroupNode.ts +0 -437
- package/src/materials/group/index.ts +0 -542
- package/src/materials/node-selection/index.ts +0 -380
- package/src/mindmap/fakerRoot.ts +0 -19
- package/src/mindmap/index.ts +0 -328
- package/src/mindmap/markContent.ts +0 -81
- package/src/mindmap/markContentOption.ts +0 -81
- package/src/mindmap/markEntity.ts +0 -82
- package/src/mindmap/markRoot.ts +0 -83
- package/src/mindmap/theme.ts +0 -11
- package/src/pool/LaneModel.ts +0 -226
- package/src/pool/LaneView.ts +0 -220
- package/src/pool/PoolModel.ts +0 -631
- package/src/pool/PoolView.ts +0 -75
- package/src/pool/constant.ts +0 -19
- package/src/pool/index.ts +0 -621
- package/src/pool/utils.ts +0 -46
- package/src/rect-label-node/RectLabelNodeView.ts +0 -33
- package/src/rect-label-node/index.ts +0 -15
- package/src/style/index.less +0 -381
- package/src/style/raw.ts +0 -328
- package/src/tools/auto-layout/index.ts +0 -282
- package/src/tools/flow-path/index.ts +0 -233
- package/src/tools/label/Label.tsx +0 -357
- package/src/tools/label/LabelModel.ts +0 -83
- package/src/tools/label/LabelOverlay.tsx +0 -162
- package/src/tools/label/algorithm.ts +0 -42
- package/src/tools/label/index.ts +0 -479
- package/src/tools/label/mediumEditor.ts +0 -121
- package/src/tools/label/utils.ts +0 -395
- package/src/tools/proximity-connect/index.ts +0 -435
- package/src/tools/snapshot/README.md +0 -145
- package/src/tools/snapshot/index.ts +0 -701
- package/src/tools/snapshot/utils.ts +0 -163
- package/src/turbo-adapter/index.ts +0 -212
- package/stats.html +0 -4842
- package/tsconfig.json +0 -18
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
import LogicFlow, {
|
|
2
|
-
Model,
|
|
3
|
-
twoPointDistance,
|
|
4
|
-
BaseNodeModel,
|
|
5
|
-
BaseEdgeModel,
|
|
6
|
-
isInNode,
|
|
7
|
-
} from '@logicflow/core'
|
|
8
|
-
import { assign, isEmpty, isEqual, isNil, isFinite, reduce } from 'lodash-es'
|
|
9
|
-
|
|
10
|
-
import AnchorConfig = Model.AnchorConfig
|
|
11
|
-
import Point = LogicFlow.Point
|
|
12
|
-
|
|
13
|
-
export type ProximityConnectProps = {
|
|
14
|
-
enable: boolean
|
|
15
|
-
distance: number
|
|
16
|
-
reverseDirection: boolean
|
|
17
|
-
virtualEdgeStyle: Record<string, unknown>
|
|
18
|
-
/**
|
|
19
|
-
* proximityConnect 类型:
|
|
20
|
-
* - 'node': 节点-节点连接
|
|
21
|
-
* - 'anchor': 锚点-锚点连接
|
|
22
|
-
* - 'default': 节点-锚点连接
|
|
23
|
-
*/
|
|
24
|
-
type: 'node' | 'anchor' | 'default'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class ProximityConnect {
|
|
28
|
-
static pluginName = 'proximityConnect'
|
|
29
|
-
enable: boolean = true
|
|
30
|
-
type: 'node' | 'anchor' | 'default' = 'default'
|
|
31
|
-
lf: LogicFlow // lf实例
|
|
32
|
-
closestNode?: BaseNodeModel // 当前距离最近的节点
|
|
33
|
-
currentDistance: number = Infinity // 当前间距
|
|
34
|
-
thresholdDistance: number = 100 // 节点-节点连接距离阈值
|
|
35
|
-
|
|
36
|
-
currentNode?: BaseNodeModel // 当前操作节点
|
|
37
|
-
reverseDirection: boolean = false // 节点-节点连线方向,默认是拖拽节点连向最近节点
|
|
38
|
-
|
|
39
|
-
currentAnchor?: AnchorConfig // 当前连线锚点
|
|
40
|
-
closestAnchor?: AnchorConfig // 当前距离最近锚点
|
|
41
|
-
virtualEdge?: BaseEdgeModel // 虚拟边
|
|
42
|
-
virtualEdgeStyle: Record<string, unknown> = {
|
|
43
|
-
strokeDasharray: '10,10',
|
|
44
|
-
stroke: '#acacac',
|
|
45
|
-
} // 虚拟边样式
|
|
46
|
-
|
|
47
|
-
constructor({
|
|
48
|
-
lf,
|
|
49
|
-
options,
|
|
50
|
-
}: LogicFlow.IExtensionProps & { options: ProximityConnectProps }) {
|
|
51
|
-
this.lf = lf
|
|
52
|
-
assign(this, options)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
render() {
|
|
56
|
-
this.addEventListeners()
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// 增加节点拖拽和锚点拖拽的事件监听
|
|
60
|
-
addEventListeners() {
|
|
61
|
-
// 节点开始拖拽事件
|
|
62
|
-
this.lf.graphModel.eventCenter.on('node:dragstart', ({ data }) => {
|
|
63
|
-
if (this.type === 'anchor') return
|
|
64
|
-
if (!this.enable) return
|
|
65
|
-
const { graphModel } = this.lf
|
|
66
|
-
const { id } = data
|
|
67
|
-
this.currentNode = graphModel.getNodeModelById(id)
|
|
68
|
-
})
|
|
69
|
-
// 节点拖拽事件
|
|
70
|
-
this.lf.graphModel.eventCenter.on('node:drag', () => {
|
|
71
|
-
if (this.type === 'anchor') return
|
|
72
|
-
this.handleNodeDrag()
|
|
73
|
-
})
|
|
74
|
-
// 锚点开始拖拽事件
|
|
75
|
-
this.lf.graphModel.eventCenter.on(
|
|
76
|
-
'anchor:dragstart',
|
|
77
|
-
({ data, nodeModel }) => {
|
|
78
|
-
if (!this.enable || this.type === 'node') return
|
|
79
|
-
this.currentNode = nodeModel
|
|
80
|
-
this.currentAnchor = data
|
|
81
|
-
},
|
|
82
|
-
)
|
|
83
|
-
// 锚点拖拽事件
|
|
84
|
-
this.lf.graphModel.eventCenter.on(
|
|
85
|
-
'anchor:drag',
|
|
86
|
-
({ e: { clientX, clientY } }) => {
|
|
87
|
-
if (!this.enable || this.type === 'node') return
|
|
88
|
-
this.handleAnchorDrag(clientX, clientY)
|
|
89
|
-
},
|
|
90
|
-
)
|
|
91
|
-
// 节点、锚点拖拽结束事件
|
|
92
|
-
this.lf.graphModel.eventCenter.on('node:drop', () => {
|
|
93
|
-
if (!this.enable || this.type === 'anchor') return
|
|
94
|
-
this.handleDrop()
|
|
95
|
-
})
|
|
96
|
-
// 锚点拖拽需要单独判断一下当前拖拽终点是否在某个锚点上,如果是,就不触发插件的连线,以免出现创建了两条连线的问题,表现见 issue 2140
|
|
97
|
-
this.lf.graphModel.eventCenter.on('anchor:dragend', ({ e, edgeModel }) => {
|
|
98
|
-
if (!this.enable || this.type === 'node') return
|
|
99
|
-
const {
|
|
100
|
-
canvasOverlayPosition: { x: eventX, y: eventY },
|
|
101
|
-
} = this.lf.graphModel.getPointByClient({
|
|
102
|
-
x: e.clientX,
|
|
103
|
-
y: e.clientY,
|
|
104
|
-
})
|
|
105
|
-
if (edgeModel && this.virtualEdge) {
|
|
106
|
-
const { id: virtualEdgeId } = this.virtualEdge as BaseEdgeModel
|
|
107
|
-
const { targetNodeId } = edgeModel as BaseEdgeModel
|
|
108
|
-
const targetNodeModel =
|
|
109
|
-
this.lf.graphModel.getNodeModelById(targetNodeId)
|
|
110
|
-
if (
|
|
111
|
-
targetNodeModel &&
|
|
112
|
-
isInNode({ x: eventX, y: eventY }, targetNodeModel, 10)
|
|
113
|
-
) {
|
|
114
|
-
// 如果当前拖拽点在锚点上,就不触发插件的连线
|
|
115
|
-
this.lf.deleteEdge(virtualEdgeId)
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
this.handleDrop()
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 节点拖拽动作
|
|
125
|
-
handleNodeDrag() {
|
|
126
|
-
/**
|
|
127
|
-
* 主要做几件事情
|
|
128
|
-
* 判断当前是否有虚拟连线,有的话判断两点距离是否超过阈值,超过的话删除连线
|
|
129
|
-
* 遍历画布上的所有节点,找到距离最近的节点,获取其所有锚点数据
|
|
130
|
-
* 判断每个锚点与当前选中节点的所有锚点之间的距离,找到路路径最短的两个点时,把当前节点、当前锚点当前最短记录记录下来,作为当前最近数据
|
|
131
|
-
* 判断当前最短距离是否小于阈值
|
|
132
|
-
* 如果是 就创建虚拟边
|
|
133
|
-
*/
|
|
134
|
-
const { nodes } = this.lf.graphModel
|
|
135
|
-
|
|
136
|
-
if (!isNil(this.virtualEdge)) {
|
|
137
|
-
const { startPoint, endPoint, id } = this.virtualEdge
|
|
138
|
-
const curDistance = twoPointDistance(startPoint, endPoint)
|
|
139
|
-
if (curDistance > this.thresholdDistance) {
|
|
140
|
-
this.lf.deleteEdge(id)
|
|
141
|
-
this.virtualEdge = undefined
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
if (this.currentNode) {
|
|
145
|
-
this.findClosestAnchorOfNode(this.currentNode, nodes)
|
|
146
|
-
}
|
|
147
|
-
if (this.currentDistance < this.thresholdDistance) {
|
|
148
|
-
this.addVirtualEdge()
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 节点放下
|
|
153
|
-
handleDrop() {
|
|
154
|
-
this.addActualEdge()
|
|
155
|
-
this.resetData()
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 锚点拖拽动作
|
|
159
|
-
handleAnchorDrag(clientX: number, clientY: number) {
|
|
160
|
-
// 获取当前点在画布上的位置
|
|
161
|
-
const { graphModel } = this.lf
|
|
162
|
-
const {
|
|
163
|
-
canvasOverlayPosition: { x, y },
|
|
164
|
-
} = graphModel.getPointByClient({
|
|
165
|
-
x: clientX,
|
|
166
|
-
y: clientY,
|
|
167
|
-
})
|
|
168
|
-
if (isNil(x) || isNil(y)) return
|
|
169
|
-
const currentPoint: Point = { x, y }
|
|
170
|
-
const { nodes } = graphModel
|
|
171
|
-
// 判断当前是否有虚拟连线,有的话判断两点距离是否超过阈值,超过的话删除连线
|
|
172
|
-
if (!isNil(this.virtualEdge)) {
|
|
173
|
-
const { endPoint, id } = this.virtualEdge
|
|
174
|
-
const curDistance = twoPointDistance(currentPoint, endPoint)
|
|
175
|
-
if (curDistance > this.thresholdDistance) {
|
|
176
|
-
this.lf.deleteEdge(id)
|
|
177
|
-
this.virtualEdge = undefined
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// 记录最近点的信息
|
|
181
|
-
this.findClosestAnchorOfAnchor(currentPoint, nodes)
|
|
182
|
-
if (this.currentDistance < this.thresholdDistance) {
|
|
183
|
-
this.addVirtualEdge()
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// 节点→节点 找最近的节点和锚点
|
|
188
|
-
findClosestAnchorOfNode(
|
|
189
|
-
draggingNode: BaseNodeModel,
|
|
190
|
-
allNodes: BaseNodeModel[],
|
|
191
|
-
) {
|
|
192
|
-
if (isNil(draggingNode) || isEmpty(draggingNode)) return
|
|
193
|
-
const { anchors: draggingAnchors = [], id } = draggingNode
|
|
194
|
-
let distance
|
|
195
|
-
let preConnectAnchor
|
|
196
|
-
let closestAnchor
|
|
197
|
-
let closestNode
|
|
198
|
-
allNodes.forEach((node) => {
|
|
199
|
-
if (isEqual(node.id, id)) return
|
|
200
|
-
const { anchors = [] } = node
|
|
201
|
-
// 遍历所有节点,找离当前拖拽节点最近的可连接节点和锚点
|
|
202
|
-
anchors.forEach((anchor) => {
|
|
203
|
-
// 找距离最近的两个锚点
|
|
204
|
-
draggingAnchors.forEach((draggingAnchor) => {
|
|
205
|
-
// 判断拖拽点锚点和当前锚点是否可连线
|
|
206
|
-
const anchorAllowConnect = this.anchorAllowConnect(
|
|
207
|
-
node,
|
|
208
|
-
anchor,
|
|
209
|
-
draggingAnchor,
|
|
210
|
-
)
|
|
211
|
-
if (!anchorAllowConnect) return
|
|
212
|
-
// 获取两个锚点之间的距离
|
|
213
|
-
const curDistance = twoPointDistance(draggingAnchor, anchor)
|
|
214
|
-
if (!distance || curDistance < distance) {
|
|
215
|
-
// 如果是第一条数据,或者当前这对锚点距离更短,就替换数据
|
|
216
|
-
distance = curDistance
|
|
217
|
-
preConnectAnchor = draggingAnchor
|
|
218
|
-
closestAnchor = anchor
|
|
219
|
-
closestNode = node
|
|
220
|
-
}
|
|
221
|
-
})
|
|
222
|
-
})
|
|
223
|
-
})
|
|
224
|
-
this.currentDistance = distance
|
|
225
|
-
this.currentAnchor = preConnectAnchor
|
|
226
|
-
this.closestAnchor = closestAnchor
|
|
227
|
-
this.closestNode = closestNode
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// 锚点→节点 找最近的锚点
|
|
231
|
-
findClosestAnchorOfAnchor(draggingPoint: Point, allNodes: BaseNodeModel[]) {
|
|
232
|
-
if (isNil(draggingPoint)) return
|
|
233
|
-
let distance
|
|
234
|
-
let closestAnchor
|
|
235
|
-
let closestNode
|
|
236
|
-
const { currentNode, currentAnchor } = this
|
|
237
|
-
allNodes.forEach((node) => {
|
|
238
|
-
if (!currentNode) return
|
|
239
|
-
const { anchors = [] } = node
|
|
240
|
-
// 遍历所有节点,找离当前拖拽节点最近的可连接节点和锚点
|
|
241
|
-
anchors.forEach((anchor) => {
|
|
242
|
-
if (isEqual(this.currentAnchor?.id, anchor.id)) return
|
|
243
|
-
// 判断拖拽点锚点和当前锚点是否可连线
|
|
244
|
-
const anchorAllowConnect = this.anchorAllowConnect(
|
|
245
|
-
node,
|
|
246
|
-
anchor,
|
|
247
|
-
currentAnchor,
|
|
248
|
-
)
|
|
249
|
-
if (!anchorAllowConnect) return
|
|
250
|
-
// 获取两个锚点之间的距离
|
|
251
|
-
const curDistance = twoPointDistance(draggingPoint, anchor)
|
|
252
|
-
if (!distance || curDistance < distance) {
|
|
253
|
-
// 如果是第一条数据,或者当前这对锚点距离更短,就替换数据
|
|
254
|
-
distance = curDistance
|
|
255
|
-
closestAnchor = anchor
|
|
256
|
-
closestNode = node
|
|
257
|
-
}
|
|
258
|
-
})
|
|
259
|
-
})
|
|
260
|
-
this.currentDistance = distance
|
|
261
|
-
this.closestAnchor = closestAnchor
|
|
262
|
-
this.closestNode = closestNode
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// 判断锚点是否允许连线
|
|
266
|
-
anchorAllowConnect(
|
|
267
|
-
node: BaseNodeModel,
|
|
268
|
-
anchor: AnchorConfig,
|
|
269
|
-
draggingAnchor: AnchorConfig | undefined,
|
|
270
|
-
) {
|
|
271
|
-
const { currentNode } = this
|
|
272
|
-
if (!currentNode) return
|
|
273
|
-
// 判断起点是否可连接
|
|
274
|
-
const { isAllPass: sourceValidResult } = this.reverseDirection
|
|
275
|
-
? node.isAllowConnectedAsSource(currentNode, anchor, draggingAnchor)
|
|
276
|
-
: currentNode.isAllowConnectedAsSource(node, draggingAnchor, anchor)
|
|
277
|
-
// 判断终点是否可连接
|
|
278
|
-
const { isAllPass: targetValidResult } = this.reverseDirection
|
|
279
|
-
? currentNode.isAllowConnectedAsTarget(node, anchor, draggingAnchor)
|
|
280
|
-
: node.isAllowConnectedAsTarget(currentNode, draggingAnchor, anchor)
|
|
281
|
-
return sourceValidResult && targetValidResult
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// 判断是否应该删除虚拟边
|
|
285
|
-
sameEdgeIsExist(edge: BaseEdgeModel) {
|
|
286
|
-
if (
|
|
287
|
-
isNil(this.closestNode) ||
|
|
288
|
-
isNil(this.currentNode) ||
|
|
289
|
-
isNil(this.closestAnchor) ||
|
|
290
|
-
isNil(this.currentAnchor)
|
|
291
|
-
)
|
|
292
|
-
return false
|
|
293
|
-
if (isNil(edge)) return false
|
|
294
|
-
const {
|
|
295
|
-
closestNode: { id: closestNodeId },
|
|
296
|
-
currentNode: { id: currentNodeId },
|
|
297
|
-
closestAnchor: { id: closestAnchorId },
|
|
298
|
-
currentAnchor: { id: currentAnchorId },
|
|
299
|
-
reverseDirection,
|
|
300
|
-
} = this
|
|
301
|
-
const { sourceNodeId, targetNodeId, sourceAnchorId, targetAnchorId } = edge
|
|
302
|
-
const isExist = reverseDirection
|
|
303
|
-
? isEqual(closestNodeId, sourceNodeId) &&
|
|
304
|
-
isEqual(currentNodeId, targetNodeId) &&
|
|
305
|
-
isEqual(closestAnchorId, sourceAnchorId) &&
|
|
306
|
-
isEqual(currentAnchorId, targetAnchorId)
|
|
307
|
-
: isEqual(currentNodeId, sourceNodeId) &&
|
|
308
|
-
isEqual(closestNodeId, targetNodeId) &&
|
|
309
|
-
isEqual(currentAnchorId, sourceAnchorId) &&
|
|
310
|
-
isEqual(closestAnchorId, targetAnchorId)
|
|
311
|
-
return isExist
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// 增加虚拟边
|
|
315
|
-
addVirtualEdge() {
|
|
316
|
-
const { edges } = this.lf.graphModel
|
|
317
|
-
// 判断当前是否已存在一条同样配置的真实边
|
|
318
|
-
const actualEdgeIsExist = reduce(
|
|
319
|
-
edges,
|
|
320
|
-
(result, edge) => {
|
|
321
|
-
if (edge.virtual) return result
|
|
322
|
-
return result || this.sameEdgeIsExist(edge)
|
|
323
|
-
},
|
|
324
|
-
false,
|
|
325
|
-
)
|
|
326
|
-
// 如果有真实边就不重复创建边了
|
|
327
|
-
if (actualEdgeIsExist) return
|
|
328
|
-
|
|
329
|
-
// 判断当前是否有虚拟边
|
|
330
|
-
// 如果当前已有虚拟边,判断当前的节点和锚点信息与虚拟边的信息是否一致
|
|
331
|
-
if (!isNil(this.virtualEdge)) {
|
|
332
|
-
const {
|
|
333
|
-
virtualEdge: { id: edgeId },
|
|
334
|
-
} = this
|
|
335
|
-
// 信息一致不做处理
|
|
336
|
-
if (this.sameEdgeIsExist(this.virtualEdge)) return
|
|
337
|
-
// 不一致就删除老边
|
|
338
|
-
this.lf.deleteEdge(edgeId)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// 开始创建虚拟边
|
|
342
|
-
const {
|
|
343
|
-
reverseDirection,
|
|
344
|
-
currentNode,
|
|
345
|
-
closestNode,
|
|
346
|
-
currentAnchor,
|
|
347
|
-
closestAnchor,
|
|
348
|
-
} = this
|
|
349
|
-
if (isEmpty(currentNode) || isEmpty(closestNode)) return
|
|
350
|
-
const properties = {
|
|
351
|
-
style: this.virtualEdgeStyle,
|
|
352
|
-
}
|
|
353
|
-
this.virtualEdge = this.lf.addEdge(
|
|
354
|
-
reverseDirection
|
|
355
|
-
? {
|
|
356
|
-
sourceNodeId: closestNode?.id,
|
|
357
|
-
targetNodeId: currentNode?.id,
|
|
358
|
-
sourceAnchorId: closestAnchor?.id,
|
|
359
|
-
targetAnchorId: currentAnchor?.id,
|
|
360
|
-
properties,
|
|
361
|
-
}
|
|
362
|
-
: {
|
|
363
|
-
sourceNodeId: currentNode?.id,
|
|
364
|
-
targetNodeId: closestNode?.id,
|
|
365
|
-
sourceAnchorId: currentAnchor?.id,
|
|
366
|
-
targetAnchorId: closestAnchor?.id,
|
|
367
|
-
properties,
|
|
368
|
-
},
|
|
369
|
-
)
|
|
370
|
-
this.virtualEdge.virtual = true
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// 增加实体边
|
|
374
|
-
addActualEdge() {
|
|
375
|
-
if (isNil(this.virtualEdge)) return
|
|
376
|
-
const {
|
|
377
|
-
type,
|
|
378
|
-
sourceNodeId,
|
|
379
|
-
targetNodeId,
|
|
380
|
-
sourceAnchorId,
|
|
381
|
-
targetAnchorId,
|
|
382
|
-
startPoint,
|
|
383
|
-
endPoint,
|
|
384
|
-
pointsList,
|
|
385
|
-
} = this.virtualEdge
|
|
386
|
-
this.lf.deleteEdge(this.virtualEdge.id)
|
|
387
|
-
this.lf.addEdge({
|
|
388
|
-
type,
|
|
389
|
-
sourceNodeId,
|
|
390
|
-
targetNodeId,
|
|
391
|
-
sourceAnchorId,
|
|
392
|
-
targetAnchorId,
|
|
393
|
-
startPoint,
|
|
394
|
-
endPoint,
|
|
395
|
-
pointsList,
|
|
396
|
-
})
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// 设置虚拟边样式
|
|
400
|
-
public setVirtualEdgeStyle(value: Record<string, unknown>) {
|
|
401
|
-
this.virtualEdgeStyle = {
|
|
402
|
-
...this.virtualEdgeStyle,
|
|
403
|
-
...value,
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// 设置连线阈值
|
|
408
|
-
public setThresholdDistance(distance: number) {
|
|
409
|
-
if (!isFinite(distance)) return
|
|
410
|
-
this.thresholdDistance = distance
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// 设置连线方向
|
|
414
|
-
public setReverseDirection(value: boolean) {
|
|
415
|
-
this.reverseDirection = value
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// 设置插件开关状态
|
|
419
|
-
public setEnable(enable: boolean) {
|
|
420
|
-
this.enable = enable
|
|
421
|
-
if (!enable) {
|
|
422
|
-
this.resetData()
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// 重置数据
|
|
427
|
-
resetData() {
|
|
428
|
-
this.closestNode = undefined
|
|
429
|
-
this.currentDistance = Infinity
|
|
430
|
-
this.currentNode = undefined
|
|
431
|
-
this.currentAnchor = undefined
|
|
432
|
-
this.closestAnchor = undefined
|
|
433
|
-
this.virtualEdge = undefined
|
|
434
|
-
}
|
|
435
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# 导出 Snapshot
|
|
2
|
-
|
|
3
|
-
我们经常需要将画布内容通过图片的形式导出来,我们提供了一个独立的插件包 `Snapshot` 来使用这个功能。
|
|
4
|
-
|
|
5
|
-
## 使用
|
|
6
|
-
|
|
7
|
-
### 1. 注册
|
|
8
|
-
|
|
9
|
-
两种注册方式,全局注册和局部注册,区别是全局注册每一个`lf`实例都可以使用。
|
|
10
|
-
|
|
11
|
-
```tsx | pure
|
|
12
|
-
import LogicFlow from "@logicflow/core";
|
|
13
|
-
import { Snapshot } from "@logicflow/extension";
|
|
14
|
-
|
|
15
|
-
// 全局注册
|
|
16
|
-
LogicFlow.use(Snapshot);
|
|
17
|
-
|
|
18
|
-
// 局部注册
|
|
19
|
-
const lf = new LogicFlow({
|
|
20
|
-
...config,
|
|
21
|
-
plugins: [Snapshot]
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### 2. 使用
|
|
27
|
-
|
|
28
|
-
注册后,`lf`实例身上将被挂载`getSnapshot()`方法,通过`lf.getSnapshot()`方法调用。
|
|
29
|
-
|
|
30
|
-
```tsx | pure
|
|
31
|
-
|
|
32
|
-
// 可以使用任意方式触发,然后将绘制的图形下载到本地磁盘上
|
|
33
|
-
document.getElementById("button").addEventListener("click", () => {
|
|
34
|
-
lf.getSnapshot();
|
|
35
|
-
|
|
36
|
-
// 或者 1.1.13版本
|
|
37
|
-
// lf.extension.snapshot.getSnapshot()
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
值得一提的是:通过此插件截取下载的图片不会因为偏移、缩放受到影响。
|
|
43
|
-
|
|
44
|
-
## 自定义设置 css
|
|
45
|
-
|
|
46
|
-
当自定义元素在导出图片时需要额外添加 css 样式时,可以用如下方式实现:
|
|
47
|
-
|
|
48
|
-
为了保持流程图生成的图片与画布上效果一致,`snapshot`插件默认会将当前页面所有的 `css` 规则都加载到导出图片中,
|
|
49
|
-
但是可能会因为 css 文件跨域引起报错,参考 issue575。可以修改useGlobalRules来禁止加载所有 css
|
|
50
|
-
规则,然后通过`customCssRules`属性来自定义增加css样式。
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
|
|
54
|
-
// 默认开启css样式
|
|
55
|
-
lf.extension.snapshot.useGlobalRules = true
|
|
56
|
-
// 不会覆盖css样式,会叠加,customCssRules优先级高
|
|
57
|
-
lf.extension.snapshot.customCssRules = `
|
|
58
|
-
.uml-wrapper {
|
|
59
|
-
line-height: 1.2;
|
|
60
|
-
text-align: center;
|
|
61
|
-
color: blue;
|
|
62
|
-
}
|
|
63
|
-
`
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## API
|
|
68
|
-
|
|
69
|
-
### lf.getSnapshot(...)
|
|
70
|
-
|
|
71
|
-
导出图片。
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
|
|
75
|
-
const getSnapshot = (fileName?: string, toImageOptions?: ToImageOptions): Promise<void> => {}
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
`fileName` 为文件名称,不填为默认为`logic-flow.当前时间戳`,`ToImageOptions` 描述如下:
|
|
80
|
-
|
|
81
|
-
| 属性名 | 类型 | 默认值 | 必填 | 描述 |
|
|
82
|
-
|-----------------|---------|-----|----|----------------------------------------------------------------------------------------|
|
|
83
|
-
| fileType | string | png | | 图片类型: 默认不填是png 还可以设置有webp、gif、jpeg、svg |
|
|
84
|
-
| width | number | - | | 自定义导出图片的宽度,不设置即可,设置可能会拉伸图形 |
|
|
85
|
-
| height | number | - | | 自定义导出图片的宽度,不设置即可,设置可能会拉伸图形 |
|
|
86
|
-
| backgroundColor | string | - | | 图片背景,不设置背景默认透明 |
|
|
87
|
-
| quality | number | - | | 图片质量,在指定图片格式为 jpeg 或 webp 的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他不合法参数会被忽略 |
|
|
88
|
-
| padding | number | 40 | | 图片内边距: 元素内容所在区之外空白空间,不设置默认有40的内边距 |
|
|
89
|
-
| partial | boolean | - | | 导出时是否开启局部渲染,false:将导出画布上所有的元素,true:只导出画面区域内的可见元素,不设置默认为lf实例身上partial值 |
|
|
90
|
-
|
|
91
|
-
注意:
|
|
92
|
-
|
|
93
|
-
- `svg`目前暂不支持`width`,`height`, `backgroundColor`, `padding` 属性。
|
|
94
|
-
- 自定义宽高后,可能会拉伸图形,这时候`padding`也会被拉伸导致不准确。
|
|
95
|
-
|
|
96
|
-
### lf.getSnapshotBlob(...)
|
|
97
|
-
|
|
98
|
-
`snapshot`
|
|
99
|
-
除了支持图片类型导出,还支持下载<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Blob" target="_blank">
|
|
100
|
-
Blob文件对象 </a>
|
|
101
|
-
和 <a href="https://developer.mozilla.org/zh-CN/docs/Glossary/Base64" target="_blank">
|
|
102
|
-
Base64文本编码 </a>
|
|
103
|
-
|
|
104
|
-
获取`Blob`对象。
|
|
105
|
-
|
|
106
|
-
```ts
|
|
107
|
-
|
|
108
|
-
const getSnapshotBlob = async (
|
|
109
|
-
backgroundColor?: string,
|
|
110
|
-
fileType?: string
|
|
111
|
-
): Promise<SnapshotResponse> => {}
|
|
112
|
-
|
|
113
|
-
// example
|
|
114
|
-
const { data: blob } = await lf.getSnapshotBlob()
|
|
115
|
-
console.log(blob)
|
|
116
|
-
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
`backgroundColor`: 背景,不填默认为透明。
|
|
120
|
-
|
|
121
|
-
`fileType`: 文件类型,不填默认为png。
|
|
122
|
-
|
|
123
|
-
`SnapshotResponse`: 返回对象。
|
|
124
|
-
|
|
125
|
-
```tsx | pure
|
|
126
|
-
|
|
127
|
-
export type SnapshotResponse = {
|
|
128
|
-
data: Blob | string // Blob对象 或 Base64文本编码文本
|
|
129
|
-
width: number // 图片宽度
|
|
130
|
-
height: number // 图片高度
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### lf.getSnapshotBase64(...)
|
|
136
|
-
|
|
137
|
-
获取`Base64文本编码`文本。
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
|
|
141
|
-
async getSnapshotBase64(backgroundColor?: string, fileType?: string) : Promise<SnapshotResponse>
|
|
142
|
-
|
|
143
|
-
// example
|
|
144
|
-
const { data : base64 } = await lf.getSnapshotBlob()
|
|
145
|
-
console.log(base64)
|