@logicflow/core 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/package.json +6 -1
- package/.turbo/turbo-build$colon$dev.log +0 -10
- package/.turbo/turbo-build.log +0 -33
- package/CHANGELOG.md +0 -1901
- package/__tests__/algorithm/egde.test.ts +0 -131
- package/__tests__/algorithm/index.test.ts +0 -74
- package/__tests__/algorithm/outline.test.ts +0 -43
- package/__tests__/bugs/1545-spec.test.ts +0 -42
- package/__tests__/event/event.test.ts +0 -22
- package/__tests__/history/history.test.ts +0 -28
- package/__tests__/logicflow.test.ts +0 -575
- package/__tests__/model/graphmodel.test.ts +0 -87
- package/__tests__/util/compatible.test.ts +0 -48
- package/__tests__/util/edge.test.ts +0 -224
- package/__tests__/util/geometry.test.ts +0 -14
- package/__tests__/util/graph.test.ts +0 -16
- package/__tests__/util/matrix.test.ts +0 -41
- package/__tests__/util/node.test.ts +0 -68
- package/__tests__/util/sampling.test.ts +0 -12
- package/__tests__/util/vector.test.ts +0 -50
- package/__tests__/util/zIndex.test.ts +0 -10
- package/src/LogicFlow.tsx +0 -2017
- package/src/algorithm/edge.ts +0 -67
- package/src/algorithm/index.ts +0 -70
- package/src/algorithm/outline.ts +0 -77
- package/src/algorithm/rotate.ts +0 -55
- package/src/common/drag.ts +0 -219
- package/src/common/history.ts +0 -108
- package/src/common/index.ts +0 -6
- package/src/common/keyboard.ts +0 -108
- package/src/common/matrix.ts +0 -122
- package/src/common/vector.ts +0 -93
- package/src/constant/index.ts +0 -179
- package/src/constant/theme.ts +0 -708
- package/src/event/event.md +0 -66
- package/src/event/eventArgs.ts +0 -643
- package/src/event/eventEmitter.ts +0 -156
- package/src/history/index.ts +0 -119
- package/src/index.less +0 -1
- package/src/index.ts +0 -26
- package/src/keyboard/index.ts +0 -112
- package/src/keyboard/shortcut.ts +0 -200
- package/src/model/BaseModel.ts +0 -250
- package/src/model/EditConfigModel.ts +0 -334
- package/src/model/GraphModel.ts +0 -1824
- package/src/model/NestedTransformModel.ts +0 -121
- package/src/model/SnaplineModel.ts +0 -256
- package/src/model/TransformModel.ts +0 -258
- package/src/model/edge/BaseEdgeModel.ts +0 -785
- package/src/model/edge/BezierEdgeModel.ts +0 -197
- package/src/model/edge/LineEdgeModel.ts +0 -36
- package/src/model/edge/PolylineEdgeModel.ts +0 -817
- package/src/model/edge/index.ts +0 -4
- package/src/model/index.ts +0 -9
- package/src/model/node/BaseNodeModel.ts +0 -959
- package/src/model/node/CircleNodeModel.ts +0 -91
- package/src/model/node/DiamondNodeModel.ts +0 -132
- package/src/model/node/EllipseNodeModel.ts +0 -98
- package/src/model/node/HtmlNodeModel.ts +0 -64
- package/src/model/node/PolygonNodeModel.ts +0 -152
- package/src/model/node/RectNodeModel.ts +0 -69
- package/src/model/node/TextNodeModel.ts +0 -54
- package/src/model/node/index.ts +0 -8
- package/src/options.ts +0 -150
- package/src/style/index.less +0 -262
- package/src/style/raw.ts +0 -221
- package/src/tool/MultipleSelectTool.tsx +0 -140
- package/src/tool/TextEditTool.tsx +0 -193
- package/src/tool/index.ts +0 -101
- package/src/typings.d.ts +0 -5
- package/src/util/animation.ts +0 -29
- package/src/util/browser.ts +0 -4
- package/src/util/compatible.ts +0 -15
- package/src/util/drag.ts +0 -219
- package/src/util/edge.ts +0 -1094
- package/src/util/geometry.ts +0 -154
- package/src/util/graph.ts +0 -46
- package/src/util/index.ts +0 -17
- package/src/util/matrix.ts +0 -129
- package/src/util/mobx.ts +0 -23
- package/src/util/node.ts +0 -543
- package/src/util/raf.ts +0 -28
- package/src/util/resize.ts +0 -606
- package/src/util/sampling.ts +0 -85
- package/src/util/theme.ts +0 -84
- package/src/util/uuid.ts +0 -26
- package/src/util/vector.ts +0 -93
- package/src/util/zIndex.ts +0 -6
- package/src/view/Anchor.tsx +0 -462
- package/src/view/Control.tsx +0 -510
- package/src/view/Graph.tsx +0 -141
- package/src/view/Rotate.tsx +0 -113
- package/src/view/behavior/dnd.ts +0 -162
- package/src/view/behavior/index.ts +0 -2
- package/src/view/behavior/snapline.ts +0 -16
- package/src/view/edge/AdjustPoint.tsx +0 -425
- package/src/view/edge/Arrow.tsx +0 -54
- package/src/view/edge/BaseEdge.tsx +0 -660
- package/src/view/edge/BezierEdge.tsx +0 -101
- package/src/view/edge/LineEdge.tsx +0 -81
- package/src/view/edge/PolylineEdge.tsx +0 -311
- package/src/view/edge/index.ts +0 -6
- package/src/view/index.ts +0 -8
- package/src/view/node/BaseNode.tsx +0 -585
- package/src/view/node/CircleNode.tsx +0 -21
- package/src/view/node/DiamondNode.tsx +0 -24
- package/src/view/node/EllipseNode.tsx +0 -22
- package/src/view/node/HtmlNode.tsx +0 -112
- package/src/view/node/PolygonNode.tsx +0 -28
- package/src/view/node/RectNode.tsx +0 -30
- package/src/view/node/TextNode.tsx +0 -39
- package/src/view/node/index.ts +0 -8
- package/src/view/overlay/BackgroundOverlay.tsx +0 -34
- package/src/view/overlay/BezierAdjustOverlay.tsx +0 -150
- package/src/view/overlay/CanvasOverlay.tsx +0 -290
- package/src/view/overlay/Grid.tsx +0 -319
- package/src/view/overlay/ModificationOverlay.tsx +0 -31
- package/src/view/overlay/OutlineOverlay.tsx +0 -158
- package/src/view/overlay/SnaplineOverlay.tsx +0 -44
- package/src/view/overlay/ToolOverlay.tsx +0 -65
- package/src/view/overlay/getTransformHoc.tsx +0 -50
- package/src/view/overlay/gridConfig.ts +0 -103
- package/src/view/overlay/index.ts +0 -8
- package/src/view/shape/Circle.tsx +0 -41
- package/src/view/shape/Ellipse.tsx +0 -42
- package/src/view/shape/Line.tsx +0 -39
- package/src/view/shape/Path.tsx +0 -22
- package/src/view/shape/Polygon.tsx +0 -54
- package/src/view/shape/Polyline.tsx +0 -31
- package/src/view/shape/Rect.tsx +0 -44
- package/src/view/shape/Text.tsx +0 -168
- package/src/view/shape/index.ts +0 -8
- package/src/view/text/BaseText.tsx +0 -134
- package/src/view/text/LineText.tsx +0 -168
- package/src/view/text/index.ts +0 -2
- package/stats.html +0 -4842
- package/tsconfig.json +0 -18
|
@@ -1,585 +0,0 @@
|
|
|
1
|
-
import { createElement as h, Component } from 'preact/compat'
|
|
2
|
-
import { reaction, IReactionDisposer } from 'mobx'
|
|
3
|
-
import { map, isFunction, isNil } from 'lodash-es'
|
|
4
|
-
import Anchor from '../Anchor'
|
|
5
|
-
import { BaseText } from '../text'
|
|
6
|
-
import LogicFlow from '../../LogicFlow'
|
|
7
|
-
import { GraphModel, BaseNodeModel, Model } from '../../model'
|
|
8
|
-
import { ElementState, EventType, TextMode } from '../../constant'
|
|
9
|
-
import {
|
|
10
|
-
StepDrag,
|
|
11
|
-
snapToGrid,
|
|
12
|
-
isIe,
|
|
13
|
-
isMultipleSelect,
|
|
14
|
-
cancelRaf,
|
|
15
|
-
createRaf,
|
|
16
|
-
IDragParams,
|
|
17
|
-
// RotateMatrix,
|
|
18
|
-
} from '../../util'
|
|
19
|
-
import RotateControlPoint from '../Rotate'
|
|
20
|
-
import ResizeControlGroup from '../Control'
|
|
21
|
-
|
|
22
|
-
type IProps = {
|
|
23
|
-
model: BaseNodeModel
|
|
24
|
-
graphModel: GraphModel
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
type IState = {
|
|
28
|
-
isDragging?: boolean
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export abstract class BaseNode<P extends IProps = IProps> extends Component<
|
|
32
|
-
P,
|
|
33
|
-
IState
|
|
34
|
-
> {
|
|
35
|
-
static isObserved: boolean = false
|
|
36
|
-
static extendsKey?: string
|
|
37
|
-
|
|
38
|
-
t: any
|
|
39
|
-
moveOffset?: LogicFlow.OffsetData
|
|
40
|
-
|
|
41
|
-
stepDrag: StepDrag
|
|
42
|
-
mouseUpDrag?: boolean
|
|
43
|
-
startTime?: number
|
|
44
|
-
modelDisposer: IReactionDisposer
|
|
45
|
-
longPressTimer?: number
|
|
46
|
-
mouseDownPosition?: LogicFlow.Position
|
|
47
|
-
|
|
48
|
-
constructor(props: IProps) {
|
|
49
|
-
super()
|
|
50
|
-
const {
|
|
51
|
-
graphModel: { gridSize, eventCenter },
|
|
52
|
-
model,
|
|
53
|
-
} = props
|
|
54
|
-
// 不在构造函数中判断,因为editConfig可能会被动态改变
|
|
55
|
-
this.stepDrag = new StepDrag({
|
|
56
|
-
onDragStart: this.onDragStart,
|
|
57
|
-
onDragging: this.onDragging,
|
|
58
|
-
onDragEnd: this.onDragEnd,
|
|
59
|
-
step: gridSize,
|
|
60
|
-
eventType: 'NODE',
|
|
61
|
-
isStopPropagation: false,
|
|
62
|
-
eventCenter,
|
|
63
|
-
model,
|
|
64
|
-
})
|
|
65
|
-
// https://github.com/didi/LogicFlow/issues/1370
|
|
66
|
-
// 当使用撤销功能:LogicFlow.undo()时,会重新初始化所有model数据,即LogicFlow.undo()时会新构建一个model对象
|
|
67
|
-
// 但是this.stepDrag并不会重新创建
|
|
68
|
-
// 导致this.stepDrag持有的model并没有重新赋值,因为之前的做法是构造函数中传入一个model对象
|
|
69
|
-
// 使用mobx的reaction监听能力,如果this.props.model发生变化,则进行this.stepDrag.setModel()操作
|
|
70
|
-
this.modelDisposer = reaction(
|
|
71
|
-
() => this.props,
|
|
72
|
-
(newProps) => {
|
|
73
|
-
if (newProps && newProps.model) {
|
|
74
|
-
this.stepDrag.setModel(newProps.model)
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
componentWillUnmount() {
|
|
81
|
-
if (this.modelDisposer) {
|
|
82
|
-
this.modelDisposer()
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 以下是 mobx-preact 中 componentWillUnmount 的回调逻辑,但是不知道出于什么考虑,mobx-preact 没有混入这一段逻辑
|
|
86
|
-
// @ts-ignore
|
|
87
|
-
if (this.render.$mobx) {
|
|
88
|
-
// @ts-ignore
|
|
89
|
-
this.render.$mobx.dispose()
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
componentDidMount() {}
|
|
94
|
-
|
|
95
|
-
componentDidUpdate() {}
|
|
96
|
-
|
|
97
|
-
abstract getShape(): h.JSX.Element | null
|
|
98
|
-
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
100
|
-
getAnchorShape(_anchorData?: Model.AnchorConfig): h.JSX.Element | null {
|
|
101
|
-
return null
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
getAnchors() {
|
|
105
|
-
const { model, graphModel } = this.props
|
|
106
|
-
const { isSelected, isHitable, isDragging, isShowAnchor } = model
|
|
107
|
-
if (isHitable && (isSelected || isShowAnchor) && !isDragging) {
|
|
108
|
-
return map(model.anchors, (anchor, index) => {
|
|
109
|
-
const edgeStyle = model.getAnchorLineStyle(anchor)
|
|
110
|
-
const style = model.getAnchorStyle(anchor)
|
|
111
|
-
return (
|
|
112
|
-
<Anchor
|
|
113
|
-
anchorData={anchor}
|
|
114
|
-
node={this}
|
|
115
|
-
style={style}
|
|
116
|
-
edgeStyle={edgeStyle}
|
|
117
|
-
anchorIndex={index}
|
|
118
|
-
nodeModel={model}
|
|
119
|
-
graphModel={graphModel}
|
|
120
|
-
setHoverOff={this.setHoverOff}
|
|
121
|
-
/>
|
|
122
|
-
)
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
return []
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
getRotateControl() {
|
|
129
|
-
const { model, graphModel } = this.props
|
|
130
|
-
const {
|
|
131
|
-
editConfigModel: { isSilentMode, allowRotate },
|
|
132
|
-
} = graphModel
|
|
133
|
-
const { isSelected, isHitable, rotatable, isHovered } = model
|
|
134
|
-
|
|
135
|
-
// 合并全局 allResize 和节点自身的 resizable 配置,以节点配置高于全局配置
|
|
136
|
-
const canRotate = allowRotate && rotatable // 全局开关 > 节点配置
|
|
137
|
-
|
|
138
|
-
const style = model.getRotateControlStyle()
|
|
139
|
-
if (!isSilentMode && isHitable && (isSelected || isHovered) && canRotate) {
|
|
140
|
-
return (
|
|
141
|
-
<RotateControlPoint
|
|
142
|
-
graphModel={graphModel}
|
|
143
|
-
nodeModel={model}
|
|
144
|
-
eventCenter={graphModel.eventCenter}
|
|
145
|
-
style={style}
|
|
146
|
-
/>
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
getResizeControl(): h.JSX.Element | null {
|
|
152
|
-
const { model, graphModel } = this.props
|
|
153
|
-
const {
|
|
154
|
-
editConfigModel: { isSilentMode, allowResize },
|
|
155
|
-
} = graphModel
|
|
156
|
-
const { isSelected, isHitable, resizable, isHovered } = model
|
|
157
|
-
|
|
158
|
-
// 合并全局 allResize 和节点自身的 resizable 配置,以节点配置高于全局配置
|
|
159
|
-
const canResize = allowResize && resizable // 全局开关 > 节点配置
|
|
160
|
-
const style = model.getResizeControlStyle()
|
|
161
|
-
if (!isSilentMode && isHitable && (isSelected || isHovered) && canResize) {
|
|
162
|
-
return (
|
|
163
|
-
<ResizeControlGroup
|
|
164
|
-
style={style}
|
|
165
|
-
model={model}
|
|
166
|
-
graphModel={graphModel}
|
|
167
|
-
/>
|
|
168
|
-
)
|
|
169
|
-
}
|
|
170
|
-
return null
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
getText(): h.JSX.Element | null {
|
|
174
|
-
const { model, graphModel } = this.props
|
|
175
|
-
const { editConfigModel } = graphModel
|
|
176
|
-
|
|
177
|
-
// 当 节点文本模式非 TEXT 时,不显示文本
|
|
178
|
-
if (editConfigModel.nodeTextMode !== TextMode.TEXT) return null
|
|
179
|
-
// 文本被编辑的时候,显示编辑框,不显示文本。
|
|
180
|
-
if (model.state === ElementState.TEXT_EDIT) return null
|
|
181
|
-
|
|
182
|
-
if (model.text) {
|
|
183
|
-
let draggable = false
|
|
184
|
-
if (editConfigModel.nodeTextDraggable && model.text.draggable) {
|
|
185
|
-
draggable = true
|
|
186
|
-
}
|
|
187
|
-
return (
|
|
188
|
-
<BaseText
|
|
189
|
-
editable={
|
|
190
|
-
editConfigModel.nodeTextEdit && (model.text.editable ?? true)
|
|
191
|
-
}
|
|
192
|
-
model={model}
|
|
193
|
-
graphModel={graphModel}
|
|
194
|
-
draggable={draggable}
|
|
195
|
-
/>
|
|
196
|
-
)
|
|
197
|
-
}
|
|
198
|
-
return null
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
getStateClassName() {
|
|
202
|
-
const {
|
|
203
|
-
model: { state, isDragging, isSelected },
|
|
204
|
-
} = this.props
|
|
205
|
-
let className = 'lf-node'
|
|
206
|
-
switch (state) {
|
|
207
|
-
case ElementState.ALLOW_CONNECT:
|
|
208
|
-
className += ' lf-node-allow'
|
|
209
|
-
break
|
|
210
|
-
case ElementState.NOT_ALLOW_CONNECT:
|
|
211
|
-
className += ' lf-node-not-allow'
|
|
212
|
-
break
|
|
213
|
-
default:
|
|
214
|
-
className += ' lf-node-default'
|
|
215
|
-
break
|
|
216
|
-
}
|
|
217
|
-
if (isDragging) {
|
|
218
|
-
className += ' lf-dragging'
|
|
219
|
-
}
|
|
220
|
-
if (isSelected) {
|
|
221
|
-
className += ' lf-node-selected'
|
|
222
|
-
}
|
|
223
|
-
return className
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
onDragStart = ({ event }: Partial<IDragParams>) => {
|
|
227
|
-
const { model, graphModel } = this.props
|
|
228
|
-
if (event) {
|
|
229
|
-
const {
|
|
230
|
-
canvasOverlayPosition: { x, y },
|
|
231
|
-
} = graphModel.getPointByClient({
|
|
232
|
-
x: event.clientX,
|
|
233
|
-
y: event.clientY,
|
|
234
|
-
})
|
|
235
|
-
this.moveOffset = {
|
|
236
|
-
dx: model.x - x,
|
|
237
|
-
dy: model.y - y,
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
onDragging = ({ event }: IDragParams) => {
|
|
243
|
-
const { model, graphModel } = this.props
|
|
244
|
-
const {
|
|
245
|
-
editConfigModel: { stopMoveGraph, autoExpand, snapGrid },
|
|
246
|
-
transformModel,
|
|
247
|
-
selectNodes,
|
|
248
|
-
width,
|
|
249
|
-
height,
|
|
250
|
-
gridSize,
|
|
251
|
-
} = graphModel
|
|
252
|
-
const { clientX, clientY } = event!
|
|
253
|
-
const { x: mouseDownX, y: mouseDownY } = this.mouseDownPosition!
|
|
254
|
-
if (clientX - mouseDownX > gridSize || clientY - mouseDownY > gridSize) {
|
|
255
|
-
model.isDragging = true
|
|
256
|
-
}
|
|
257
|
-
let {
|
|
258
|
-
canvasOverlayPosition: { x, y },
|
|
259
|
-
} = graphModel.getPointByClient({
|
|
260
|
-
x: clientX,
|
|
261
|
-
y: clientY,
|
|
262
|
-
})
|
|
263
|
-
const [x1, y1] = transformModel.CanvasPointToHtmlPoint([x, y])
|
|
264
|
-
// 1. 考虑画布被缩放
|
|
265
|
-
// 2. 考虑鼠标位置不再节点中心
|
|
266
|
-
x = x + (this.moveOffset?.dx ?? 0)
|
|
267
|
-
y = y + (this.moveOffset?.dy ?? 0)
|
|
268
|
-
// 校准坐标
|
|
269
|
-
x = snapToGrid(x, gridSize, snapGrid)
|
|
270
|
-
y = snapToGrid(y, gridSize, snapGrid)
|
|
271
|
-
if (!width || !height) {
|
|
272
|
-
graphModel.moveNode2Coordinate(model.id, x, y)
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
const isOutCanvas = x1 < 0 || y1 < 0 || x1 > width || y1 > height
|
|
276
|
-
if (autoExpand && !stopMoveGraph && isOutCanvas) {
|
|
277
|
-
// 鼠标超出画布后的拖动,不处理,而是让上一次setInterval持续滚动画布
|
|
278
|
-
return
|
|
279
|
-
}
|
|
280
|
-
// 取节点左上角和右下角,计算节点移动是否超出范围
|
|
281
|
-
const [leftTopX, leftTopY] = transformModel.CanvasPointToHtmlPoint([
|
|
282
|
-
x - model.width / 2,
|
|
283
|
-
y - model.height / 2,
|
|
284
|
-
])
|
|
285
|
-
const [rightBottomX, rightBottomY] = transformModel.CanvasPointToHtmlPoint([
|
|
286
|
-
x + model.width / 2,
|
|
287
|
-
y + model.height / 2,
|
|
288
|
-
])
|
|
289
|
-
const size: number = Math.max(gridSize, 20)
|
|
290
|
-
let nearBoundary: LogicFlow.PointTuple | [] = []
|
|
291
|
-
if (leftTopX < 0) {
|
|
292
|
-
nearBoundary = [size, 0]
|
|
293
|
-
} else if (rightBottomX > graphModel.width) {
|
|
294
|
-
nearBoundary = [-size, 0]
|
|
295
|
-
} else if (leftTopY < 0) {
|
|
296
|
-
nearBoundary = [0, size]
|
|
297
|
-
} else if (rightBottomY > graphModel.height) {
|
|
298
|
-
nearBoundary = [0, -size]
|
|
299
|
-
}
|
|
300
|
-
if (this.t) {
|
|
301
|
-
cancelRaf(this.t)
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
let moveNodes = selectNodes.map((node) => node.id)
|
|
305
|
-
// 未被选中的节点也可以拖动
|
|
306
|
-
if (moveNodes.indexOf(model.id) === -1) {
|
|
307
|
-
moveNodes = [model.id]
|
|
308
|
-
}
|
|
309
|
-
if (nearBoundary.length > 0 && !stopMoveGraph && autoExpand) {
|
|
310
|
-
this.t = createRaf(() => {
|
|
311
|
-
const [translateX, translateY] = nearBoundary
|
|
312
|
-
transformModel.translate(translateX ?? 0, translateY ?? 0)
|
|
313
|
-
const deltaX = -(translateX ?? 0) / transformModel.SCALE_X
|
|
314
|
-
const deltaY = -(translateY ?? 0) / transformModel.SCALE_X
|
|
315
|
-
graphModel.moveNodes(moveNodes, deltaX, deltaY)
|
|
316
|
-
})
|
|
317
|
-
} else {
|
|
318
|
-
graphModel.moveNodes(moveNodes, x - model.x, y - model.y)
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
onDragEnd = () => {
|
|
323
|
-
if (this.t) {
|
|
324
|
-
cancelRaf(this.t)
|
|
325
|
-
}
|
|
326
|
-
const { model } = this.props
|
|
327
|
-
model.isDragging = false
|
|
328
|
-
}
|
|
329
|
-
onMouseOut = (ev: MouseEvent) => {
|
|
330
|
-
if (isIe()) {
|
|
331
|
-
this.setHoverOff(ev)
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
handleMouseUp = () => {
|
|
336
|
-
const { model } = this.props
|
|
337
|
-
this.mouseUpDrag = model.isDragging
|
|
338
|
-
if (this.longPressTimer) {
|
|
339
|
-
clearTimeout(this.longPressTimer)
|
|
340
|
-
this.longPressTimer = undefined
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
handleClick = (e: MouseEvent) => {
|
|
345
|
-
// 节点拖拽进画布之后,不触发click事件相关emit
|
|
346
|
-
// 点拖拽进画布没有触发mousedown事件,没有startTime,用这个值做区分
|
|
347
|
-
const isDragging = this.mouseUpDrag === false
|
|
348
|
-
const curTime = new Date().getTime()
|
|
349
|
-
if (!this.startTime) return
|
|
350
|
-
const timeInterval = curTime - this.startTime
|
|
351
|
-
const { model, graphModel } = this.props
|
|
352
|
-
// 这里会有一种极端情况:当网格大小是1或者关闭网格吸附时,用触摸板点击节点会触发拖拽事件导致节点无法选中
|
|
353
|
-
// 当触摸板点击节点时,为了防止误触发拖拽导致节点无法选中,允许在非拖拽状态且时间间隔小于100ms时触发点击事件
|
|
354
|
-
if (!isDragging && timeInterval > 300) return
|
|
355
|
-
if (!isDragging) {
|
|
356
|
-
this.onDragEnd()
|
|
357
|
-
this.handleMouseUp()
|
|
358
|
-
}
|
|
359
|
-
// 节点数据,多为事件对象数据抛出
|
|
360
|
-
const nodeData = model.getData()
|
|
361
|
-
const position = graphModel.getPointByClient({
|
|
362
|
-
x: e.clientX,
|
|
363
|
-
y: e.clientY,
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
// TODO: 这里加入了 isSelected 与 isMultiple,主要是为 group 插件做的加强,有种被插件夺舍的感觉
|
|
367
|
-
const eventOptions = {
|
|
368
|
-
data: nodeData,
|
|
369
|
-
e,
|
|
370
|
-
position,
|
|
371
|
-
isSelected: false,
|
|
372
|
-
isMultiple: false,
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
const isRightClick = e.button === 2
|
|
376
|
-
// 这里 IE 11不能正确显示
|
|
377
|
-
const isDoubleClick = e.detail === 2
|
|
378
|
-
|
|
379
|
-
// 判断是否有右击,如果有右击则取消点击事件触发
|
|
380
|
-
if (isRightClick) return
|
|
381
|
-
|
|
382
|
-
const { editConfigModel } = graphModel
|
|
383
|
-
// 在multipleSelect tool禁用的情况下,允许取消选中节点
|
|
384
|
-
const isMultiple = isMultipleSelect(e, editConfigModel)
|
|
385
|
-
eventOptions.isMultiple = isMultiple
|
|
386
|
-
if (model.isSelected && !isDoubleClick && isMultiple) {
|
|
387
|
-
eventOptions.isSelected = false
|
|
388
|
-
model.setSelected(false)
|
|
389
|
-
} else {
|
|
390
|
-
graphModel.selectNodeById(model.id, isMultiple)
|
|
391
|
-
eventOptions.isSelected = true
|
|
392
|
-
// 静默模式下点击节点不变更节点层级
|
|
393
|
-
if (!editConfigModel.isSilentMode) {
|
|
394
|
-
this.toFront()
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// 不是双击的,默认都是单击
|
|
399
|
-
if (isDoubleClick) {
|
|
400
|
-
if (editConfigModel.nodeTextEdit) {
|
|
401
|
-
if (model.text.editable && editConfigModel.textMode === TextMode.TEXT) {
|
|
402
|
-
model.setSelected(false)
|
|
403
|
-
graphModel.setElementStateById(model.id, ElementState.TEXT_EDIT)
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
graphModel.eventCenter.emit(EventType.NODE_DBCLICK, eventOptions)
|
|
407
|
-
} else {
|
|
408
|
-
graphModel.eventCenter.emit(EventType.ELEMENT_CLICK, eventOptions)
|
|
409
|
-
graphModel.eventCenter.emit(EventType.NODE_CLICK, eventOptions)
|
|
410
|
-
// 复制粘贴后会出现点击节点时,节点会失去焦点的问题,这里手动让节点获焦以解决这个问题
|
|
411
|
-
const el = e.currentTarget as HTMLElement
|
|
412
|
-
const rAF =
|
|
413
|
-
!isNil(window) && isFunction(window.requestAnimationFrame)
|
|
414
|
-
? window.requestAnimationFrame.bind(window)
|
|
415
|
-
: (fn: () => void) => setTimeout(fn, 0)
|
|
416
|
-
rAF(() => {
|
|
417
|
-
el.focus()
|
|
418
|
-
})
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
handleContextMenu = (ev: MouseEvent) => {
|
|
423
|
-
ev.preventDefault()
|
|
424
|
-
const { model, graphModel } = this.props
|
|
425
|
-
const { editConfigModel } = graphModel
|
|
426
|
-
// 节点数据,多为事件对象数据抛出
|
|
427
|
-
const nodeData = model.getData()
|
|
428
|
-
|
|
429
|
-
const position = graphModel.getPointByClient({
|
|
430
|
-
x: ev.clientX,
|
|
431
|
-
y: ev.clientY,
|
|
432
|
-
})
|
|
433
|
-
graphModel.setElementStateById(
|
|
434
|
-
model.id,
|
|
435
|
-
ElementState.SHOW_MENU,
|
|
436
|
-
position.domOverlayPosition,
|
|
437
|
-
)
|
|
438
|
-
if (!model.isSelected) {
|
|
439
|
-
graphModel.selectNodeById(model.id)
|
|
440
|
-
}
|
|
441
|
-
graphModel.eventCenter.emit(EventType.NODE_CONTEXTMENU, {
|
|
442
|
-
data: nodeData,
|
|
443
|
-
e: ev,
|
|
444
|
-
position,
|
|
445
|
-
})
|
|
446
|
-
// 静默模式下点击节点不变更节点层级
|
|
447
|
-
if (!editConfigModel.isSilentMode) {
|
|
448
|
-
this.toFront()
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
handleMouseDown = (ev: PointerEvent) => {
|
|
453
|
-
const { model, graphModel } = this.props
|
|
454
|
-
this.mouseDownPosition = { x: ev.clientX, y: ev.clientY }
|
|
455
|
-
this.startTime = new Date().getTime()
|
|
456
|
-
const { editConfigModel } = graphModel
|
|
457
|
-
if (editConfigModel.adjustNodePosition && model.draggable) {
|
|
458
|
-
this.stepDrag && this.stepDrag.handleMouseDown(ev)
|
|
459
|
-
}
|
|
460
|
-
if (this.longPressTimer) {
|
|
461
|
-
clearTimeout(this.longPressTimer)
|
|
462
|
-
}
|
|
463
|
-
if (ev.pointerType === 'touch') {
|
|
464
|
-
this.longPressTimer = window.setTimeout(() => {
|
|
465
|
-
if (!this.props.model.isDragging) {
|
|
466
|
-
this.handleContextMenu(ev)
|
|
467
|
-
}
|
|
468
|
-
}, 500)
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
handleFocus = () => {
|
|
473
|
-
const { model, graphModel } = this.props
|
|
474
|
-
graphModel.eventCenter.emit(EventType.NODE_FOCUS, {
|
|
475
|
-
data: model.getData(),
|
|
476
|
-
})
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
handleBlur = () => {
|
|
480
|
-
// 当节点通过自定义锚点实现节点删除时,这里props会变成undefined,需兼容一下
|
|
481
|
-
if (!this.props) return
|
|
482
|
-
const { model, graphModel } = this.props
|
|
483
|
-
graphModel.eventCenter.emit(EventType.NODE_BLUR, {
|
|
484
|
-
data: model.getData(),
|
|
485
|
-
})
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// 因为自定义节点的时候,可能会基于hover状态自定义不同的样式。
|
|
489
|
-
setHoverOn = (ev: MouseEvent) => {
|
|
490
|
-
const { model, graphModel } = this.props
|
|
491
|
-
if (model.isHovered) return
|
|
492
|
-
const nodeData = model.getData()
|
|
493
|
-
model.setHovered(true)
|
|
494
|
-
graphModel.eventCenter.emit(EventType.NODE_MOUSEENTER, {
|
|
495
|
-
data: nodeData,
|
|
496
|
-
e: ev,
|
|
497
|
-
})
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
setHoverOff = (ev: MouseEvent) => {
|
|
501
|
-
const { model, graphModel } = this.props
|
|
502
|
-
const nodeData = model.getData()
|
|
503
|
-
// 文本focus时,关联的元素也需要高亮,所以元素失焦时还要判断下是否有文本处于focus状态
|
|
504
|
-
if (!model.isHovered) return
|
|
505
|
-
model.setHovered(false)
|
|
506
|
-
graphModel.eventCenter.emit(EventType.NODE_MOUSELEAVE, {
|
|
507
|
-
data: nodeData,
|
|
508
|
-
e: ev,
|
|
509
|
-
})
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* @overridable 支持重写, 节点置顶,可以被某些不需要置顶的节点重写,如group节点。
|
|
514
|
-
*/
|
|
515
|
-
toFront() {
|
|
516
|
-
const { model, graphModel } = this.props
|
|
517
|
-
if (model.autoToFront) {
|
|
518
|
-
graphModel.toFront(model.id)
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
render() {
|
|
523
|
-
const { model, graphModel } = this.props
|
|
524
|
-
const {
|
|
525
|
-
editConfigModel: {
|
|
526
|
-
hideAnchors,
|
|
527
|
-
adjustNodePosition,
|
|
528
|
-
allowRotate,
|
|
529
|
-
allowResize,
|
|
530
|
-
},
|
|
531
|
-
gridSize,
|
|
532
|
-
transformModel: { SCALE_X },
|
|
533
|
-
} = graphModel
|
|
534
|
-
const { isHitable, draggable, transform } = model
|
|
535
|
-
const { className = '', ...restAttributes } = model.getOuterGAttributes()
|
|
536
|
-
const nodeShapeInner = (
|
|
537
|
-
<g className="lf-node-content">
|
|
538
|
-
<g transform={transform}>
|
|
539
|
-
{this.getShape()}
|
|
540
|
-
{this.getText()}
|
|
541
|
-
{allowResize && this.getResizeControl()}
|
|
542
|
-
{allowRotate && this.getRotateControl()}
|
|
543
|
-
</g>
|
|
544
|
-
{!hideAnchors && this.getAnchors()}
|
|
545
|
-
</g>
|
|
546
|
-
)
|
|
547
|
-
let nodeShape: h.JSX.Element
|
|
548
|
-
if (!isHitable) {
|
|
549
|
-
nodeShape = (
|
|
550
|
-
<g
|
|
551
|
-
className={`${this.getStateClassName()} ${className}`}
|
|
552
|
-
{...restAttributes}
|
|
553
|
-
>
|
|
554
|
-
{nodeShapeInner}
|
|
555
|
-
</g>
|
|
556
|
-
)
|
|
557
|
-
} else {
|
|
558
|
-
if (adjustNodePosition && draggable) {
|
|
559
|
-
this.stepDrag.setStep(gridSize * SCALE_X)
|
|
560
|
-
}
|
|
561
|
-
nodeShape = (
|
|
562
|
-
<g
|
|
563
|
-
className={`${this.getStateClassName()} ${className}`}
|
|
564
|
-
onPointerDown={this.handleMouseDown}
|
|
565
|
-
onPointerUp={this.handleMouseUp}
|
|
566
|
-
onClick={this.handleClick}
|
|
567
|
-
//因为移动端点击操作完成会按顺序触发enter、leave、click事件,所以会造成节点的闪烁,所以在这里没有统一状态为Pointer
|
|
568
|
-
onMouseEnter={this.setHoverOn}
|
|
569
|
-
onMouseOver={this.setHoverOn}
|
|
570
|
-
onMouseLeave={this.setHoverOff}
|
|
571
|
-
onMouseOut={this.onMouseOut}
|
|
572
|
-
onContextMenu={this.handleContextMenu}
|
|
573
|
-
onFocus={this.handleFocus}
|
|
574
|
-
onBlur={this.handleBlur}
|
|
575
|
-
{...restAttributes}
|
|
576
|
-
>
|
|
577
|
-
{nodeShapeInner}
|
|
578
|
-
</g>
|
|
579
|
-
)
|
|
580
|
-
}
|
|
581
|
-
return nodeShape
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
export default BaseNode
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import Circle from '../shape/Circle'
|
|
2
|
-
import BaseNode from './BaseNode'
|
|
3
|
-
import { GraphModel, CircleNodeModel } from '../../model'
|
|
4
|
-
|
|
5
|
-
export type ICircleNodeProps = {
|
|
6
|
-
model: CircleNodeModel
|
|
7
|
-
graphModel: GraphModel
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class CircleNode<
|
|
11
|
-
P extends ICircleNodeProps = ICircleNodeProps,
|
|
12
|
-
> extends BaseNode<P> {
|
|
13
|
-
getShape() {
|
|
14
|
-
const { model } = this.props
|
|
15
|
-
const { x, y, r } = model
|
|
16
|
-
const style = model.getNodeStyle()
|
|
17
|
-
return <Circle {...style} x={x} y={y} r={r} />
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default CircleNode
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import BaseNode from './BaseNode'
|
|
2
|
-
import Polygon from '../shape/Polygon'
|
|
3
|
-
import { GraphModel, DiamondNodeModel } from '../../model'
|
|
4
|
-
|
|
5
|
-
export type IDiamondNodeProps = {
|
|
6
|
-
model: DiamondNodeModel
|
|
7
|
-
graphModel: GraphModel
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class DiamondNode<
|
|
11
|
-
P extends IDiamondNodeProps = IDiamondNodeProps,
|
|
12
|
-
> extends BaseNode<P> {
|
|
13
|
-
getShape() {
|
|
14
|
-
const { model } = this.props
|
|
15
|
-
const style = model.getNodeStyle()
|
|
16
|
-
return (
|
|
17
|
-
<g>
|
|
18
|
-
<Polygon {...style} points={model.points} x={model.x} y={model.y} />
|
|
19
|
-
</g>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default DiamondNode
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import BaseNode from './BaseNode'
|
|
2
|
-
import Ellipse from '../shape/Ellipse'
|
|
3
|
-
import { GraphModel, EllipseNodeModel } from '../../model'
|
|
4
|
-
|
|
5
|
-
export type IEllipseNodeProps = {
|
|
6
|
-
model: EllipseNodeModel
|
|
7
|
-
graphModel: GraphModel
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class EllipseNode<
|
|
11
|
-
P extends IEllipseNodeProps = IEllipseNodeProps,
|
|
12
|
-
> extends BaseNode<P> {
|
|
13
|
-
getShape() {
|
|
14
|
-
const { model } = this.props
|
|
15
|
-
const style = model.getNodeStyle()
|
|
16
|
-
return (
|
|
17
|
-
<Ellipse {...style} x={model.x} y={model.y} rx={model.rx} ry={model.ry} />
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export default EllipseNode
|