@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,817 +0,0 @@
|
|
|
1
|
-
import { get, assign, cloneDeep } from 'lodash-es'
|
|
2
|
-
import { observable, action } from 'mobx'
|
|
3
|
-
import { BaseEdgeModel } from '.'
|
|
4
|
-
import { BaseNodeModel, RectNodeModel, CircleNodeModel, Model } from '..'
|
|
5
|
-
import LogicFlow from '../../LogicFlow'
|
|
6
|
-
import { ModelType, SegmentDirection } from '../../constant'
|
|
7
|
-
import {
|
|
8
|
-
isInNode,
|
|
9
|
-
distance,
|
|
10
|
-
getClosestRadiusCenter,
|
|
11
|
-
inStraightLineOfRect,
|
|
12
|
-
getCrossPointWithCircle,
|
|
13
|
-
getCrossPointWithEllipse,
|
|
14
|
-
getCrossPointWithPolygon,
|
|
15
|
-
getPolylinePoints,
|
|
16
|
-
getLongestEdge,
|
|
17
|
-
getCrossPointInRect,
|
|
18
|
-
isSegmentsInNode,
|
|
19
|
-
isSegmentsCrossNode,
|
|
20
|
-
segmentDirection,
|
|
21
|
-
points2PointsList,
|
|
22
|
-
pointFilter,
|
|
23
|
-
} from '../../util'
|
|
24
|
-
|
|
25
|
-
import Point = LogicFlow.Point
|
|
26
|
-
import Position = LogicFlow.Position
|
|
27
|
-
import AppendConfig = LogicFlow.AppendConfig
|
|
28
|
-
import AnchorConfig = Model.AnchorConfig
|
|
29
|
-
|
|
30
|
-
export class PolylineEdgeModel extends BaseEdgeModel {
|
|
31
|
-
modelType = ModelType.POLYLINE_EDGE
|
|
32
|
-
draggingPointList: Point[] = []
|
|
33
|
-
@observable offset?: number
|
|
34
|
-
@observable dbClickPosition?: Point
|
|
35
|
-
|
|
36
|
-
initEdgeData(data: LogicFlow.EdgeConfig): void {
|
|
37
|
-
const providedOffset = get(data, 'properties.offset')
|
|
38
|
-
// 当用户未传入 offset 时,按“箭头与折线重叠长度 + 5”作为默认值
|
|
39
|
-
// 其中“重叠长度”采用箭头样式中的 offset(沿边方向的长度)
|
|
40
|
-
this.offset =
|
|
41
|
-
typeof providedOffset === 'number'
|
|
42
|
-
? providedOffset
|
|
43
|
-
: this.getDefaultOffset()
|
|
44
|
-
if (data.pointsList) {
|
|
45
|
-
const corrected = this.orthogonalizePath(data.pointsList)
|
|
46
|
-
;(data as any).pointsList = corrected
|
|
47
|
-
this.pointsList = corrected
|
|
48
|
-
}
|
|
49
|
-
super.initEdgeData(data)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
setAttributes() {
|
|
53
|
-
const { offset: newOffset } = this.properties
|
|
54
|
-
if (newOffset && newOffset !== this.offset) {
|
|
55
|
-
this.offset = newOffset
|
|
56
|
-
this.updatePoints()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
orthogonalizePath(points: Point[]): Point[] {
|
|
61
|
-
// 输入非法或不足两点时直接返回副本
|
|
62
|
-
if (!Array.isArray(points) || points.length < 2) {
|
|
63
|
-
return points
|
|
64
|
-
}
|
|
65
|
-
// pushUnique: 向数组中添加唯一点,避免重复
|
|
66
|
-
const pushUnique = (arr: Point[], p: Point) => {
|
|
67
|
-
const last = arr[arr.length - 1]
|
|
68
|
-
if (!last || last.x !== p.x || last.y !== p.y) {
|
|
69
|
-
arr.push({ x: p.x, y: p.y })
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// isAxisAligned: 检查两点是否在同一条轴上
|
|
73
|
-
const isAxisAligned = (a: Point, b: Point) => a.x === b.x || a.y === b.y
|
|
74
|
-
// manhattanDistance: 计算两点在曼哈顿距离上的距离
|
|
75
|
-
const manhattanDistance = (a: Point, b: Point) =>
|
|
76
|
-
Math.abs(a.x - b.x) + Math.abs(a.y - b.y)
|
|
77
|
-
|
|
78
|
-
// 1) 生成严格正交路径,尽量延续前一段方向以减少折点
|
|
79
|
-
const orthogonal: Point[] = []
|
|
80
|
-
pushUnique(orthogonal, points[0])
|
|
81
|
-
// previousDirection: 记录前一段的方向,用于判断当前段的PreferredCorner
|
|
82
|
-
let previousDirection: SegmentDirection | undefined
|
|
83
|
-
// 遍历所有点对,生成正交路径
|
|
84
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
85
|
-
const current = orthogonal[orthogonal.length - 1]
|
|
86
|
-
const next = points[i + 1]
|
|
87
|
-
if (!current || !next) continue
|
|
88
|
-
|
|
89
|
-
if (isAxisAligned(current, next)) {
|
|
90
|
-
pushUnique(orthogonal, next)
|
|
91
|
-
previousDirection =
|
|
92
|
-
current.x === next.x
|
|
93
|
-
? SegmentDirection.VERTICAL
|
|
94
|
-
: SegmentDirection.HORIZONTAL
|
|
95
|
-
continue
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const cornerHV: Point = { x: next.x, y: current.y }
|
|
99
|
-
const cornerVH: Point = { x: current.x, y: next.y }
|
|
100
|
-
|
|
101
|
-
// 根据前一段的方向,优先选择能延续该方向的拐角点,以减少折点数量;
|
|
102
|
-
// 若前一段为垂直方向,则优先选择垂直-水平拐角(cornerVH);
|
|
103
|
-
// 若前一段为水平方向,则优先选择水平-垂直拐角(cornerHV);
|
|
104
|
-
// 若前一段无方向(初始情况),则比较两个拐角的曼哈顿距离,选更近者。
|
|
105
|
-
const preferredCorner =
|
|
106
|
-
previousDirection === SegmentDirection.VERTICAL
|
|
107
|
-
? cornerVH
|
|
108
|
-
: previousDirection === SegmentDirection.HORIZONTAL
|
|
109
|
-
? cornerHV
|
|
110
|
-
: manhattanDistance(current, cornerHV) <=
|
|
111
|
-
manhattanDistance(current, cornerVH)
|
|
112
|
-
? cornerHV
|
|
113
|
-
: cornerVH
|
|
114
|
-
|
|
115
|
-
if (preferredCorner.x !== current.x || preferredCorner.y !== current.y) {
|
|
116
|
-
pushUnique(orthogonal, preferredCorner)
|
|
117
|
-
}
|
|
118
|
-
pushUnique(orthogonal, next)
|
|
119
|
-
|
|
120
|
-
const a = orthogonal[orthogonal.length - 2]
|
|
121
|
-
const b = orthogonal[orthogonal.length - 1]
|
|
122
|
-
previousDirection =
|
|
123
|
-
a && b
|
|
124
|
-
? a.x === b.x
|
|
125
|
-
? SegmentDirection.VERTICAL
|
|
126
|
-
: SegmentDirection.HORIZONTAL
|
|
127
|
-
: previousDirection
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// 2) 去除冗余共线中间点
|
|
131
|
-
const simplified: Point[] = []
|
|
132
|
-
for (let i = 0; i < orthogonal.length; i++) {
|
|
133
|
-
const prev = orthogonal[i - 1]
|
|
134
|
-
const curr = orthogonal[i]
|
|
135
|
-
const next = orthogonal[i + 1]
|
|
136
|
-
// 如果当前点与前一个点和后一个点在同一条水平线或垂直线上,则跳过该点,去除冗余的共线中间点
|
|
137
|
-
if (
|
|
138
|
-
prev &&
|
|
139
|
-
curr &&
|
|
140
|
-
next &&
|
|
141
|
-
((prev.x === curr.x && curr.x === next.x) || // 水平共线
|
|
142
|
-
(prev.y === curr.y && curr.y === next.y)) // 垂直共线
|
|
143
|
-
) {
|
|
144
|
-
continue
|
|
145
|
-
}
|
|
146
|
-
pushUnique(simplified, curr)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// 3) 保留原始起点与终点位置
|
|
150
|
-
if (simplified.length >= 2) {
|
|
151
|
-
simplified[0] = { x: points[0].x, y: points[0].y }
|
|
152
|
-
simplified[simplified.length - 1] = {
|
|
153
|
-
x: points[points.length - 1].x,
|
|
154
|
-
y: points[points.length - 1].y,
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 4) 结果校验:任意相邻段都必须为水平/垂直;失败则退化为起止两点
|
|
159
|
-
const isOrthogonal =
|
|
160
|
-
simplified.length < 2 ||
|
|
161
|
-
simplified.every((_, idx, arr) => {
|
|
162
|
-
if (idx === 0) return true
|
|
163
|
-
return isAxisAligned(arr[idx - 1], arr[idx])
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
return isOrthogonal
|
|
167
|
-
? simplified
|
|
168
|
-
: [
|
|
169
|
-
{ x: points[0].x, y: points[0].y },
|
|
170
|
-
{ x: points[points.length - 1].x, y: points[points.length - 1].y },
|
|
171
|
-
]
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* 计算默认 offset:箭头与折线重叠长度 + 5
|
|
176
|
-
* 重叠长度采用箭头样式中的 offset(沿边方向的长度)
|
|
177
|
-
*/
|
|
178
|
-
private getDefaultOffset(): number {
|
|
179
|
-
const arrowStyle = this.getArrowStyle()
|
|
180
|
-
const arrowOverlap =
|
|
181
|
-
typeof arrowStyle.offset === 'number' ? arrowStyle.offset : 0
|
|
182
|
-
return arrowOverlap + 5
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
getEdgeStyle() {
|
|
186
|
-
const { polyline } = this.graphModel.theme
|
|
187
|
-
const style = super.getEdgeStyle()
|
|
188
|
-
const { style: customStyle = {} } = this.properties
|
|
189
|
-
return {
|
|
190
|
-
...style,
|
|
191
|
-
...cloneDeep(polyline),
|
|
192
|
-
...cloneDeep(customStyle),
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
getTextPosition() {
|
|
197
|
-
// 在文本为空的情况下,文本位置为双击位置
|
|
198
|
-
const textValue = this.text?.value
|
|
199
|
-
if (this.dbClickPosition && !textValue) {
|
|
200
|
-
const { x, y } = this.dbClickPosition
|
|
201
|
-
return { x, y }
|
|
202
|
-
}
|
|
203
|
-
// 文本不为空或者没有双击位置时,取最长边的中点作为文本位置
|
|
204
|
-
const currentPositionList = points2PointsList(this.points)
|
|
205
|
-
const [p1, p2] = getLongestEdge(currentPositionList)
|
|
206
|
-
return {
|
|
207
|
-
x: (p1.x + p2.x) / 2,
|
|
208
|
-
y: (p1.y + p2.y) / 2,
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// 获取下一个锚点
|
|
213
|
-
getAfterAnchor(
|
|
214
|
-
direction: SegmentDirection,
|
|
215
|
-
position: Position,
|
|
216
|
-
anchorList: AnchorConfig[],
|
|
217
|
-
) {
|
|
218
|
-
let anchor: AnchorConfig
|
|
219
|
-
let minDistance: number
|
|
220
|
-
anchorList.forEach((item) => {
|
|
221
|
-
let distanceX: number
|
|
222
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
223
|
-
distanceX = Math.abs(position.y - item.y)
|
|
224
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
225
|
-
distanceX = Math.abs(position.x - item.x)
|
|
226
|
-
}
|
|
227
|
-
if (!minDistance || minDistance > distanceX!) {
|
|
228
|
-
minDistance = distanceX!
|
|
229
|
-
anchor = item
|
|
230
|
-
}
|
|
231
|
-
})
|
|
232
|
-
return anchor!
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/* 获取拖拽过程中产生的交点 */
|
|
236
|
-
getCrossPoint(direction: SegmentDirection, start: Position, end: Position) {
|
|
237
|
-
let position: Point
|
|
238
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
239
|
-
position = {
|
|
240
|
-
x: end.x,
|
|
241
|
-
y: start.y,
|
|
242
|
-
}
|
|
243
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
244
|
-
position = {
|
|
245
|
-
x: start.x,
|
|
246
|
-
y: end.y,
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return position!
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// 删除在图形内的过个交点
|
|
253
|
-
removeCrossPoints(startIndex: number, endIndex: number, pointList: Point[]) {
|
|
254
|
-
const list = pointList.map((i) => i)
|
|
255
|
-
if (startIndex === 1) {
|
|
256
|
-
const start = list[startIndex]
|
|
257
|
-
const end = list[endIndex]
|
|
258
|
-
const pre = list[startIndex - 1]
|
|
259
|
-
const isInStartNode = isSegmentsInNode(pre, start, this.sourceNode)
|
|
260
|
-
if (isInStartNode) {
|
|
261
|
-
const isSegmentsCrossStartNode = isSegmentsCrossNode(
|
|
262
|
-
start,
|
|
263
|
-
end,
|
|
264
|
-
this.sourceNode,
|
|
265
|
-
)
|
|
266
|
-
if (isSegmentsCrossStartNode) {
|
|
267
|
-
const point = getCrossPointInRect(start, end, this.sourceNode)
|
|
268
|
-
if (point) {
|
|
269
|
-
list[startIndex] = point
|
|
270
|
-
list.splice(startIndex - 1, 1)
|
|
271
|
-
startIndex--
|
|
272
|
-
endIndex--
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
} else {
|
|
276
|
-
const anchorList = this.sourceNode.anchors
|
|
277
|
-
anchorList.forEach((item) => {
|
|
278
|
-
if (
|
|
279
|
-
(item.x === pre.x && item.x === start.x) ||
|
|
280
|
-
(item.y === pre.y && item.y === start.y)
|
|
281
|
-
) {
|
|
282
|
-
const distance1 = distance(item.x, item.y, start.x, start.y)
|
|
283
|
-
const distance2 = distance(pre.x, pre.y, start.x, start.y)
|
|
284
|
-
if (distance1 < distance2) {
|
|
285
|
-
list[startIndex - 1] = item
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
})
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
if (endIndex === pointList.length - 2) {
|
|
292
|
-
const start = list[startIndex]
|
|
293
|
-
const end = list[endIndex]
|
|
294
|
-
const next = list[endIndex + 1]
|
|
295
|
-
const isInEndNode = isSegmentsInNode(end, next, this.targetNode)
|
|
296
|
-
if (isInEndNode) {
|
|
297
|
-
const isSegmentsCrossStartNode = isSegmentsCrossNode(
|
|
298
|
-
start,
|
|
299
|
-
end,
|
|
300
|
-
this.targetNode,
|
|
301
|
-
)
|
|
302
|
-
if (isSegmentsCrossStartNode) {
|
|
303
|
-
const point = getCrossPointInRect(start, end, this.targetNode)
|
|
304
|
-
if (point) {
|
|
305
|
-
list[endIndex] = point
|
|
306
|
-
list.splice(endIndex + 1, 1)
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
} else {
|
|
310
|
-
const anchorList = this.targetNode.anchors
|
|
311
|
-
anchorList.forEach((item) => {
|
|
312
|
-
if (
|
|
313
|
-
(item.x === next.x && item.x === end.x) ||
|
|
314
|
-
(item.y === next.y && item.y === end.y)
|
|
315
|
-
) {
|
|
316
|
-
const distance1 = distance(item.x, item.y, end.x, end.y)
|
|
317
|
-
const distance2 = distance(next.x, next.y, end.x, end.y)
|
|
318
|
-
if (distance1 < distance2) {
|
|
319
|
-
list[endIndex + 1] = item
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
})
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return list
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// 获取在拖拽过程中可能产生的点
|
|
329
|
-
getDraggingPoints(
|
|
330
|
-
direction: SegmentDirection,
|
|
331
|
-
positionType: string,
|
|
332
|
-
position: Position,
|
|
333
|
-
anchorList: AnchorConfig[],
|
|
334
|
-
draggingPointList: Point[],
|
|
335
|
-
) {
|
|
336
|
-
const pointList = draggingPointList.map((i) => i)
|
|
337
|
-
const anchor = this.getAfterAnchor(direction, position, anchorList)
|
|
338
|
-
const crossPoint = this.getCrossPoint(direction, position, anchor)
|
|
339
|
-
if (positionType === 'start') {
|
|
340
|
-
pointList.unshift(crossPoint)
|
|
341
|
-
pointList.unshift(anchor)
|
|
342
|
-
} else {
|
|
343
|
-
pointList.push(crossPoint)
|
|
344
|
-
pointList.push(anchor)
|
|
345
|
-
}
|
|
346
|
-
return pointList
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// 更新相交点[起点,终点],更加贴近图形, 未修改observable不作为action
|
|
350
|
-
updateCrossPoints(pointList: Point[]) {
|
|
351
|
-
const list = pointList.map((i) => i)
|
|
352
|
-
const start = pointList[0]
|
|
353
|
-
const next = pointList[1]
|
|
354
|
-
const pre = pointList[list.length - 2]
|
|
355
|
-
const end = pointList[list.length - 1]
|
|
356
|
-
const { sourceNode, targetNode } = this
|
|
357
|
-
const sourceModelType = sourceNode.modelType
|
|
358
|
-
const targetModelType = targetNode.modelType
|
|
359
|
-
const startPointDirection = segmentDirection(start, next)!
|
|
360
|
-
let startCrossPoint = list[0]
|
|
361
|
-
switch (sourceModelType) {
|
|
362
|
-
case ModelType.RECT_NODE:
|
|
363
|
-
if ((sourceNode as RectNodeModel).radius !== 0) {
|
|
364
|
-
const inInnerNode = inStraightLineOfRect(start, sourceNode)
|
|
365
|
-
if (!inInnerNode) {
|
|
366
|
-
startCrossPoint = getClosestRadiusCenter(
|
|
367
|
-
start,
|
|
368
|
-
startPointDirection,
|
|
369
|
-
sourceNode,
|
|
370
|
-
)
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
break
|
|
374
|
-
case ModelType.CIRCLE_NODE:
|
|
375
|
-
startCrossPoint = getCrossPointWithCircle(
|
|
376
|
-
start,
|
|
377
|
-
startPointDirection,
|
|
378
|
-
sourceNode as CircleNodeModel,
|
|
379
|
-
)
|
|
380
|
-
break
|
|
381
|
-
case ModelType.ELLIPSE_NODE:
|
|
382
|
-
startCrossPoint = getCrossPointWithEllipse(
|
|
383
|
-
start,
|
|
384
|
-
startPointDirection,
|
|
385
|
-
sourceNode,
|
|
386
|
-
)
|
|
387
|
-
break
|
|
388
|
-
case ModelType.DIAMOND_NODE:
|
|
389
|
-
startCrossPoint = getCrossPointWithPolygon(
|
|
390
|
-
start,
|
|
391
|
-
startPointDirection,
|
|
392
|
-
sourceNode,
|
|
393
|
-
)
|
|
394
|
-
break
|
|
395
|
-
case ModelType.POLYGON_NODE:
|
|
396
|
-
startCrossPoint = getCrossPointWithPolygon(
|
|
397
|
-
start,
|
|
398
|
-
startPointDirection,
|
|
399
|
-
sourceNode,
|
|
400
|
-
)
|
|
401
|
-
break
|
|
402
|
-
default:
|
|
403
|
-
break
|
|
404
|
-
}
|
|
405
|
-
// 如果线段和形状没有交点时startCrossPoint会为undefined导致后续计算报错
|
|
406
|
-
if (startCrossPoint) {
|
|
407
|
-
list[0] = startCrossPoint
|
|
408
|
-
}
|
|
409
|
-
const endPointDirection = segmentDirection(pre, end)!
|
|
410
|
-
let endCrossPoint = list[list.length - 1]
|
|
411
|
-
switch (targetModelType) {
|
|
412
|
-
case ModelType.RECT_NODE:
|
|
413
|
-
if ((targetNode as RectNodeModel).radius !== 0) {
|
|
414
|
-
const inInnerNode = inStraightLineOfRect(end, targetNode)
|
|
415
|
-
if (!inInnerNode) {
|
|
416
|
-
endCrossPoint = getClosestRadiusCenter(
|
|
417
|
-
end,
|
|
418
|
-
endPointDirection,
|
|
419
|
-
targetNode,
|
|
420
|
-
)
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
break
|
|
424
|
-
case ModelType.CIRCLE_NODE:
|
|
425
|
-
endCrossPoint = getCrossPointWithCircle(
|
|
426
|
-
end,
|
|
427
|
-
endPointDirection,
|
|
428
|
-
targetNode as CircleNodeModel,
|
|
429
|
-
)
|
|
430
|
-
break
|
|
431
|
-
case ModelType.ELLIPSE_NODE:
|
|
432
|
-
endCrossPoint = getCrossPointWithEllipse(
|
|
433
|
-
end,
|
|
434
|
-
endPointDirection,
|
|
435
|
-
targetNode,
|
|
436
|
-
)
|
|
437
|
-
break
|
|
438
|
-
case ModelType.DIAMOND_NODE:
|
|
439
|
-
endCrossPoint = getCrossPointWithPolygon(
|
|
440
|
-
end,
|
|
441
|
-
endPointDirection,
|
|
442
|
-
targetNode,
|
|
443
|
-
)
|
|
444
|
-
break
|
|
445
|
-
case ModelType.POLYGON_NODE:
|
|
446
|
-
endCrossPoint = getCrossPointWithPolygon(
|
|
447
|
-
end,
|
|
448
|
-
endPointDirection,
|
|
449
|
-
targetNode,
|
|
450
|
-
)
|
|
451
|
-
break
|
|
452
|
-
default:
|
|
453
|
-
break
|
|
454
|
-
}
|
|
455
|
-
// 如果线段和形状没有交点时startCrossPoint会为undefined导致后续计算报错
|
|
456
|
-
if (endCrossPoint) {
|
|
457
|
-
list[list.length - 1] = endCrossPoint
|
|
458
|
-
}
|
|
459
|
-
return list
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
updatePath(pointList: Point[]) {
|
|
463
|
-
this.pointsList = this.orthogonalizePath(pointList)
|
|
464
|
-
this.points = this.getPath(this.pointsList)
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
getData() {
|
|
468
|
-
const data = super.getData()
|
|
469
|
-
const pointsList = this.pointsList.map(({ x, y }) => ({
|
|
470
|
-
x,
|
|
471
|
-
y,
|
|
472
|
-
}))
|
|
473
|
-
return Object.assign({}, data, {
|
|
474
|
-
pointsList,
|
|
475
|
-
})
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
getPath(points: Point[]): string {
|
|
479
|
-
return points.map((point) => `${point.x},${point.y}`).join(' ')
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
@action
|
|
483
|
-
initPoints() {
|
|
484
|
-
if (this.pointsList.length > 0) {
|
|
485
|
-
this.points = this.getPath(this.pointsList)
|
|
486
|
-
} else {
|
|
487
|
-
this.updatePoints()
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
@action
|
|
492
|
-
updatePoints() {
|
|
493
|
-
const pointsList = getPolylinePoints(
|
|
494
|
-
{
|
|
495
|
-
x: this.startPoint.x,
|
|
496
|
-
y: this.startPoint.y,
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
x: this.endPoint.x,
|
|
500
|
-
y: this.endPoint.y,
|
|
501
|
-
},
|
|
502
|
-
this.sourceNode,
|
|
503
|
-
this.targetNode,
|
|
504
|
-
this.offset || 0,
|
|
505
|
-
)
|
|
506
|
-
this.pointsList = this.orthogonalizePath(pointsList)
|
|
507
|
-
this.points = this.pointsList
|
|
508
|
-
.map((point) => `${point.x},${point.y}`)
|
|
509
|
-
.join(' ')
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
@action
|
|
513
|
-
updateStartPoint(anchor: Point) {
|
|
514
|
-
this.startPoint = Object.assign({}, anchor)
|
|
515
|
-
this.updatePoints()
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
@action
|
|
519
|
-
moveStartPoint(deltaX: number, deltaY: number): void {
|
|
520
|
-
this.startPoint.x += deltaX
|
|
521
|
-
this.startPoint.y += deltaY
|
|
522
|
-
this.updatePoints()
|
|
523
|
-
// todo: 尽量保持边的整体轮廓, 通过deltaX和deltaY更新pointsList,而不是重新计算。
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
@action
|
|
527
|
-
updateEndPoint(anchor: Point) {
|
|
528
|
-
this.endPoint = Object.assign({}, anchor)
|
|
529
|
-
this.updatePoints()
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
@action
|
|
533
|
-
moveEndPoint(deltaX: number, deltaY: number): void {
|
|
534
|
-
this.endPoint.x += deltaX
|
|
535
|
-
this.endPoint.y += deltaY
|
|
536
|
-
this.updatePoints()
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
@action
|
|
540
|
-
updatePointsList(deltaX: number, deltaY: number): void {
|
|
541
|
-
this.pointsList.forEach((item) => {
|
|
542
|
-
item.x += deltaX
|
|
543
|
-
item.y += deltaY
|
|
544
|
-
})
|
|
545
|
-
const startPoint = this.pointsList[0]
|
|
546
|
-
this.startPoint = Object.assign({}, startPoint)
|
|
547
|
-
const endPoint = this.pointsList[this.pointsList.length - 1]
|
|
548
|
-
this.endPoint = Object.assign({}, endPoint)
|
|
549
|
-
this.initPoints()
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
@action
|
|
553
|
-
dragAppendStart() {
|
|
554
|
-
// mobx observer 对象被iterator处理会有问题
|
|
555
|
-
this.draggingPointList = this.pointsList.map((i) => i)
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
@action
|
|
559
|
-
dragAppendSimple(
|
|
560
|
-
appendInfo: AppendConfig,
|
|
561
|
-
dragInfo: Record<'x' | 'y', number>,
|
|
562
|
-
) {
|
|
563
|
-
// 因为drag事件是mouseDown事件触发的,因此当真实拖拽之后再设置isDragging
|
|
564
|
-
// 避免因为点击事件造成,在dragStart触发之后,没有触发dragEnd错误设置了isDragging状态,对history计算造成错误
|
|
565
|
-
this.isDragging = true
|
|
566
|
-
const { start, end, startIndex, endIndex, direction } = appendInfo
|
|
567
|
-
const { pointsList } = this
|
|
568
|
-
let draggingPointList = pointsList
|
|
569
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
570
|
-
// 水平,仅调整y坐标,拿到当前线段两个端点移动后的坐标
|
|
571
|
-
pointsList[startIndex] = {
|
|
572
|
-
x: start.x,
|
|
573
|
-
y: start.y + dragInfo.y,
|
|
574
|
-
}
|
|
575
|
-
pointsList[endIndex] = {
|
|
576
|
-
x: end.x,
|
|
577
|
-
y: end.y + dragInfo.y,
|
|
578
|
-
}
|
|
579
|
-
draggingPointList = this.pointsList.map((i) => i)
|
|
580
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
581
|
-
// 垂直,仅调整x坐标, 与水平调整同理
|
|
582
|
-
pointsList[startIndex] = {
|
|
583
|
-
x: start.x + dragInfo.x,
|
|
584
|
-
y: start.y,
|
|
585
|
-
}
|
|
586
|
-
pointsList[endIndex] = {
|
|
587
|
-
x: end.x + dragInfo.x,
|
|
588
|
-
y: end.y,
|
|
589
|
-
}
|
|
590
|
-
draggingPointList = this.pointsList.map((i) => i)
|
|
591
|
-
}
|
|
592
|
-
this.updatePointsAfterDrag(draggingPointList)
|
|
593
|
-
this.draggingPointList = draggingPointList
|
|
594
|
-
// TODO: 判断该逻辑是否需要
|
|
595
|
-
if (this.text?.value) {
|
|
596
|
-
this.setText(assign({}, this.text, this.textPosition))
|
|
597
|
-
}
|
|
598
|
-
return {
|
|
599
|
-
start: assign({}, pointsList[startIndex]),
|
|
600
|
-
end: assign({}, pointsList[endIndex]),
|
|
601
|
-
startIndex,
|
|
602
|
-
endIndex,
|
|
603
|
-
direction,
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
@action
|
|
608
|
-
dragAppend(appendInfo: AppendConfig, dragInfo: Record<'x' | 'y', number>) {
|
|
609
|
-
this.isDragging = true
|
|
610
|
-
const { start, end, startIndex, endIndex, direction } = appendInfo
|
|
611
|
-
const { pointsList } = this
|
|
612
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
613
|
-
// 水平,仅调整y坐标
|
|
614
|
-
// step1: 拿到当前线段两个端点移动后的坐标
|
|
615
|
-
pointsList[startIndex] = {
|
|
616
|
-
x: start.x,
|
|
617
|
-
y: start.y + dragInfo.y,
|
|
618
|
-
}
|
|
619
|
-
pointsList[endIndex] = {
|
|
620
|
-
x: end.x,
|
|
621
|
-
y: end.y + dragInfo.y,
|
|
622
|
-
}
|
|
623
|
-
// step2: 计算拖拽后,两个端点与节点外框的交点
|
|
624
|
-
// 定义一个拖住中节点list
|
|
625
|
-
let draggingPointList = this.pointsList.map((i) => i)
|
|
626
|
-
if (startIndex !== 0 && endIndex !== this.pointsList.length - 1) {
|
|
627
|
-
// 2.1)如果线段没有连接起终点,过滤会穿插在图形内部的线段,取整个图形离线段最近的点
|
|
628
|
-
draggingPointList = this.removeCrossPoints(
|
|
629
|
-
startIndex,
|
|
630
|
-
endIndex,
|
|
631
|
-
draggingPointList,
|
|
632
|
-
)
|
|
633
|
-
}
|
|
634
|
-
if (startIndex === 0) {
|
|
635
|
-
// 2.2)如果线段连接了起点, 判断起点是否在节点内部
|
|
636
|
-
const startPosition = {
|
|
637
|
-
x: start.x,
|
|
638
|
-
y: start.y + dragInfo.y,
|
|
639
|
-
}
|
|
640
|
-
const inNode = isInNode(startPosition, this.sourceNode)
|
|
641
|
-
if (!inNode) {
|
|
642
|
-
// 如果不在节点内部,更换起点为线段与节点的交点
|
|
643
|
-
const anchorList = this.sourceNode.anchors
|
|
644
|
-
draggingPointList = this.getDraggingPoints(
|
|
645
|
-
direction,
|
|
646
|
-
'start',
|
|
647
|
-
startPosition,
|
|
648
|
-
anchorList,
|
|
649
|
-
draggingPointList,
|
|
650
|
-
)
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
if (endIndex === this.pointsList.length - 1) {
|
|
654
|
-
// 2.2)如果线段连接了终点, 判断起点是否在节点内部
|
|
655
|
-
const endPosition = {
|
|
656
|
-
x: end.x,
|
|
657
|
-
y: end.y + dragInfo.y,
|
|
658
|
-
}
|
|
659
|
-
const inNode = isInNode(endPosition, this.targetNode)
|
|
660
|
-
if (!inNode) {
|
|
661
|
-
// 如果不在节点内部,更换终点为线段与节点的交点
|
|
662
|
-
const anchorList = this.targetNode.anchors
|
|
663
|
-
draggingPointList = this.getDraggingPoints(
|
|
664
|
-
direction,
|
|
665
|
-
'end',
|
|
666
|
-
endPosition,
|
|
667
|
-
anchorList,
|
|
668
|
-
draggingPointList,
|
|
669
|
-
)
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
this.updatePointsAfterDrag(draggingPointList)
|
|
673
|
-
// step3: 调整到对应外框的位置后,执行updatePointsAfterDrag,找到当前线段和图形的准确交点
|
|
674
|
-
this.draggingPointList = draggingPointList
|
|
675
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
676
|
-
// 垂直,仅调整x坐标, 与水平调整同理
|
|
677
|
-
pointsList[startIndex] = {
|
|
678
|
-
x: start.x + dragInfo.x,
|
|
679
|
-
y: start.y,
|
|
680
|
-
}
|
|
681
|
-
pointsList[endIndex] = {
|
|
682
|
-
x: end.x + dragInfo.x,
|
|
683
|
-
y: end.y,
|
|
684
|
-
}
|
|
685
|
-
let draggingPointList = this.pointsList.map((i) => i)
|
|
686
|
-
if (startIndex !== 0 && endIndex !== this.pointsList.length - 1) {
|
|
687
|
-
draggingPointList = this.removeCrossPoints(
|
|
688
|
-
startIndex,
|
|
689
|
-
endIndex,
|
|
690
|
-
draggingPointList,
|
|
691
|
-
)
|
|
692
|
-
}
|
|
693
|
-
if (startIndex === 0) {
|
|
694
|
-
const startPosition = {
|
|
695
|
-
x: start.x + dragInfo.x,
|
|
696
|
-
y: start.y,
|
|
697
|
-
}
|
|
698
|
-
const inNode = isInNode(startPosition, this.sourceNode)
|
|
699
|
-
if (!inNode) {
|
|
700
|
-
const anchorList = this.sourceNode.anchors
|
|
701
|
-
draggingPointList = this.getDraggingPoints(
|
|
702
|
-
direction,
|
|
703
|
-
'start',
|
|
704
|
-
startPosition,
|
|
705
|
-
anchorList,
|
|
706
|
-
draggingPointList,
|
|
707
|
-
)
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
if (endIndex === this.pointsList.length - 1) {
|
|
711
|
-
const endPosition = {
|
|
712
|
-
x: end.x + dragInfo.x,
|
|
713
|
-
y: end.y,
|
|
714
|
-
}
|
|
715
|
-
const inNode = isInNode(endPosition, this.targetNode)
|
|
716
|
-
if (!inNode) {
|
|
717
|
-
const anchorList = this.targetNode.anchors
|
|
718
|
-
draggingPointList = this.getDraggingPoints(
|
|
719
|
-
direction,
|
|
720
|
-
'end',
|
|
721
|
-
endPosition,
|
|
722
|
-
anchorList,
|
|
723
|
-
draggingPointList,
|
|
724
|
-
)
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
this.updatePointsAfterDrag(draggingPointList)
|
|
728
|
-
this.draggingPointList = draggingPointList
|
|
729
|
-
}
|
|
730
|
-
// TODO: 确认该判断逻辑是否需要
|
|
731
|
-
if (this.text?.value) {
|
|
732
|
-
this.setText(assign({}, this.text, this.textPosition))
|
|
733
|
-
}
|
|
734
|
-
return {
|
|
735
|
-
start: assign({}, pointsList[startIndex]),
|
|
736
|
-
end: assign({}, pointsList[endIndex]),
|
|
737
|
-
startIndex,
|
|
738
|
-
endIndex,
|
|
739
|
-
direction,
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
@action
|
|
744
|
-
dragAppendEnd() {
|
|
745
|
-
if (this.draggingPointList) {
|
|
746
|
-
const pointsList = pointFilter(points2PointsList(this.points))
|
|
747
|
-
// 更新pointsList,重新渲染appendWidth
|
|
748
|
-
this.pointsList = pointsList.map((i) => i)
|
|
749
|
-
// draggingPointList清空
|
|
750
|
-
this.draggingPointList = []
|
|
751
|
-
// 更新起终点
|
|
752
|
-
const startPoint = pointsList[0]
|
|
753
|
-
this.startPoint = assign({}, startPoint)
|
|
754
|
-
const endPoint = pointsList[pointsList.length - 1]
|
|
755
|
-
this.endPoint = assign({}, endPoint)
|
|
756
|
-
}
|
|
757
|
-
this.isDragging = false
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
/* 拖拽之后个更新points,仅更新边,不更新pointsList,
|
|
761
|
-
appendWidth会依赖pointsList,更新pointsList会重新渲染appendWidth,从而导致不能继续拖拽
|
|
762
|
-
在拖拽结束后再进行pointsList的更新
|
|
763
|
-
*/
|
|
764
|
-
@action
|
|
765
|
-
updatePointsAfterDrag(pointsList: Point[]) {
|
|
766
|
-
// 找到准确的连接点后,更新points, 更新边,同时更新依赖points的箭头
|
|
767
|
-
const list = this.updateCrossPoints(pointsList)
|
|
768
|
-
this.points = list.map((point) => `${point.x},${point.y}`).join(' ')
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
// 获取边调整的起点
|
|
772
|
-
@action
|
|
773
|
-
getAdjustStart() {
|
|
774
|
-
return this.pointsList[0] || this.startPoint
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
// 获取边调整的终点
|
|
778
|
-
@action
|
|
779
|
-
getAdjustEnd() {
|
|
780
|
-
const { pointsList } = this
|
|
781
|
-
return pointsList[pointsList.length - 1] || this.endPoint
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// 起终点拖拽调整过程中,进行折线路径更新
|
|
785
|
-
@action
|
|
786
|
-
updateAfterAdjustStartAndEnd({
|
|
787
|
-
startPoint,
|
|
788
|
-
endPoint,
|
|
789
|
-
sourceNode,
|
|
790
|
-
targetNode,
|
|
791
|
-
}: {
|
|
792
|
-
startPoint: Point
|
|
793
|
-
endPoint: Point
|
|
794
|
-
sourceNode: BaseNodeModel
|
|
795
|
-
targetNode: BaseNodeModel
|
|
796
|
-
}) {
|
|
797
|
-
this.pointsList = this.orthogonalizePath(
|
|
798
|
-
getPolylinePoints(
|
|
799
|
-
{
|
|
800
|
-
x: startPoint.x,
|
|
801
|
-
y: startPoint.y,
|
|
802
|
-
},
|
|
803
|
-
{
|
|
804
|
-
x: endPoint.x,
|
|
805
|
-
y: endPoint.y,
|
|
806
|
-
},
|
|
807
|
-
sourceNode,
|
|
808
|
-
targetNode,
|
|
809
|
-
this.offset || 0,
|
|
810
|
-
),
|
|
811
|
-
)
|
|
812
|
-
|
|
813
|
-
this.initPoints()
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
export default PolylineEdgeModel
|