@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
package/src/util/node.ts
DELETED
|
@@ -1,543 +0,0 @@
|
|
|
1
|
-
import { pick } from 'lodash-es'
|
|
2
|
-
import { createElement as h } from 'preact/compat'
|
|
3
|
-
import { getBytesLength } from './edge'
|
|
4
|
-
import LogicFlow from '../LogicFlow'
|
|
5
|
-
import {
|
|
6
|
-
GraphModel,
|
|
7
|
-
Model,
|
|
8
|
-
BaseNodeModel,
|
|
9
|
-
// CircleNodeModel,
|
|
10
|
-
RectNodeModel,
|
|
11
|
-
EllipseNodeModel,
|
|
12
|
-
PolygonNodeModel,
|
|
13
|
-
} from '../model'
|
|
14
|
-
import { SegmentDirection } from '../constant'
|
|
15
|
-
import { isInSegment } from '../algorithm/edge'
|
|
16
|
-
import { Matrix } from './matrix'
|
|
17
|
-
|
|
18
|
-
import Point = LogicFlow.Point
|
|
19
|
-
import Direction = LogicFlow.Direction
|
|
20
|
-
import NodeConfig = LogicFlow.NodeConfig
|
|
21
|
-
import LineSegment = LogicFlow.LineSegment
|
|
22
|
-
import AnchorInfo = Model.AnchorInfo
|
|
23
|
-
import BoxBoundsPoint = Model.BoxBoundsPoint
|
|
24
|
-
|
|
25
|
-
/* 获取所有锚点 */
|
|
26
|
-
export const getAnchors = (data: BaseNodeModel) => {
|
|
27
|
-
const { anchors } = data
|
|
28
|
-
return anchors
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type NodeContaint = {
|
|
32
|
-
node: BaseNodeModel
|
|
33
|
-
anchorIndex: number
|
|
34
|
-
anchor: Model.AnchorConfig
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* 手动边时获取目标节点的信息:目标节点,目标节点的锚点index以及坐标 */
|
|
38
|
-
export const targetNodeInfo = (
|
|
39
|
-
position: Point,
|
|
40
|
-
graphModel: GraphModel,
|
|
41
|
-
): NodeContaint => {
|
|
42
|
-
const { nodes } = graphModel
|
|
43
|
-
let nodeInfo: NodeContaint
|
|
44
|
-
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
45
|
-
const targetNode = nodes[i]
|
|
46
|
-
const inNode = isInNodeBbox(position, targetNode)
|
|
47
|
-
if (inNode) {
|
|
48
|
-
const anchorInfo = targetNode.getTargetAnchor(position)
|
|
49
|
-
if (anchorInfo) {
|
|
50
|
-
// 不能连接到没有锚点的节点
|
|
51
|
-
const currentNodeInfo = {
|
|
52
|
-
node: targetNode,
|
|
53
|
-
anchorIndex: anchorInfo.index,
|
|
54
|
-
anchor: anchorInfo.anchor,
|
|
55
|
-
}
|
|
56
|
-
// fix: 489 多个节点重合时,连线连接上面的那一个。
|
|
57
|
-
if (!nodeInfo! || isNodeHigher(targetNode, nodeInfo.node, graphModel)) {
|
|
58
|
-
nodeInfo = currentNodeInfo
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return nodeInfo!
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* 比较两个节点
|
|
67
|
-
*/
|
|
68
|
-
const isNodeHigher = (
|
|
69
|
-
node1: BaseNodeModel,
|
|
70
|
-
node2: BaseNodeModel,
|
|
71
|
-
graphModel: GraphModel,
|
|
72
|
-
) => {
|
|
73
|
-
if (node1.zIndex > node2.zIndex) {
|
|
74
|
-
return true
|
|
75
|
-
}
|
|
76
|
-
return (
|
|
77
|
-
graphModel.nodesMap[node1.id].index > graphModel.nodesMap[node2.id].index
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/* 手动边时获取目标节点上,距离目标位置最近的锚点 */
|
|
82
|
-
export const getClosestAnchor = (
|
|
83
|
-
position: Point,
|
|
84
|
-
node: BaseNodeModel,
|
|
85
|
-
): AnchorInfo => {
|
|
86
|
-
const anchors = getAnchors(node)
|
|
87
|
-
let closest: AnchorInfo
|
|
88
|
-
let minDistance = Number.MAX_SAFE_INTEGER
|
|
89
|
-
for (let i = 0; i < anchors.length; i++) {
|
|
90
|
-
const len = distance(position.x, position.y, anchors[i].x, anchors[i].y)
|
|
91
|
-
if (len < minDistance) {
|
|
92
|
-
minDistance = len
|
|
93
|
-
closest = {
|
|
94
|
-
index: i,
|
|
95
|
-
anchor: {
|
|
96
|
-
...anchors[i],
|
|
97
|
-
x: anchors[i].x,
|
|
98
|
-
y: anchors[i].y,
|
|
99
|
-
id: anchors[i].id,
|
|
100
|
-
},
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return closest!
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/* 两点之间距离 */
|
|
108
|
-
export const distance = (
|
|
109
|
-
x1: number,
|
|
110
|
-
y1: number,
|
|
111
|
-
x2: number,
|
|
112
|
-
y2: number,
|
|
113
|
-
): number => Math.hypot(x1 - x2, y1 - y2)
|
|
114
|
-
|
|
115
|
-
/* 是否在某个节点内,手否进行连接,有offset控制粒度,与outline有关,可以优化 */
|
|
116
|
-
export const isInNode = (
|
|
117
|
-
position: Point,
|
|
118
|
-
node: BaseNodeModel,
|
|
119
|
-
offset = 0,
|
|
120
|
-
): boolean => {
|
|
121
|
-
let inNode = false
|
|
122
|
-
const bBox = getNodeBBox(node)
|
|
123
|
-
const [x, y] = new Matrix([position.x, position.y, 1])
|
|
124
|
-
.translate(-node.x, -node.y)
|
|
125
|
-
.rotate(-node.rotate)
|
|
126
|
-
.translate(node.x, node.y)[0]
|
|
127
|
-
const reverseRotatedPosition = {
|
|
128
|
-
x,
|
|
129
|
-
y,
|
|
130
|
-
}
|
|
131
|
-
if (
|
|
132
|
-
reverseRotatedPosition.x >= bBox.minX - offset &&
|
|
133
|
-
reverseRotatedPosition.x <= bBox.maxX + offset &&
|
|
134
|
-
reverseRotatedPosition.y >= bBox.minY - offset &&
|
|
135
|
-
reverseRotatedPosition.y <= bBox.maxY + offset
|
|
136
|
-
) {
|
|
137
|
-
inNode = true
|
|
138
|
-
}
|
|
139
|
-
return inNode
|
|
140
|
-
}
|
|
141
|
-
export const isInNodeBbox = (position: Point, node: BaseNodeModel): boolean => {
|
|
142
|
-
return isInNode(position, node, 5)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export type NodeBBox = {
|
|
146
|
-
x: number
|
|
147
|
-
y: number
|
|
148
|
-
width: number
|
|
149
|
-
height: number
|
|
150
|
-
centerX: number
|
|
151
|
-
centerY: number
|
|
152
|
-
} & BoxBoundsPoint
|
|
153
|
-
|
|
154
|
-
/* 获取节点bbox */
|
|
155
|
-
export const getNodeBBox = (node: BaseNodeModel): NodeBBox => {
|
|
156
|
-
const { x, y, width, height } = node
|
|
157
|
-
return {
|
|
158
|
-
minX: x - width / 2,
|
|
159
|
-
minY: y - height / 2,
|
|
160
|
-
maxX: x + width / 2,
|
|
161
|
-
maxY: y + height / 2,
|
|
162
|
-
x,
|
|
163
|
-
y,
|
|
164
|
-
width,
|
|
165
|
-
height,
|
|
166
|
-
centerX: x,
|
|
167
|
-
centerY: y,
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
type RadiusCircle = {
|
|
171
|
-
x: number
|
|
172
|
-
y: number
|
|
173
|
-
r: number
|
|
174
|
-
}
|
|
175
|
-
export const getRectRadiusCircle = (
|
|
176
|
-
node: BaseNodeModel,
|
|
177
|
-
): [RadiusCircle, RadiusCircle, RadiusCircle, RadiusCircle] => {
|
|
178
|
-
const { x, y, width, height, radius } = node as RectNodeModel
|
|
179
|
-
return [
|
|
180
|
-
{
|
|
181
|
-
x: x - width / 2 + radius,
|
|
182
|
-
y: y - height / 2 + radius,
|
|
183
|
-
r: radius,
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
x: x + width / 2 - radius,
|
|
187
|
-
y: y - height / 2 + radius,
|
|
188
|
-
r: radius,
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
x: x - width / 2 + radius,
|
|
192
|
-
y: y + height / 2 - radius,
|
|
193
|
-
r: radius,
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
x: x + width / 2 - radius,
|
|
197
|
-
y: y + height / 2 - radius,
|
|
198
|
-
r: radius,
|
|
199
|
-
},
|
|
200
|
-
]
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export const getClosestRadiusCenter = (
|
|
204
|
-
point: Point,
|
|
205
|
-
direction: Direction,
|
|
206
|
-
node: BaseNodeModel,
|
|
207
|
-
): Point => {
|
|
208
|
-
const radiusCenter = getRectRadiusCircle(node)
|
|
209
|
-
let closestRadiusPoint: RadiusCircle
|
|
210
|
-
let minDistance = Number.MAX_SAFE_INTEGER
|
|
211
|
-
radiusCenter.forEach((item) => {
|
|
212
|
-
const radiusDistance = distance(point.x, point.y, item.x, item.y)
|
|
213
|
-
if (radiusDistance < minDistance) {
|
|
214
|
-
minDistance = radiusDistance
|
|
215
|
-
closestRadiusPoint = item
|
|
216
|
-
}
|
|
217
|
-
})
|
|
218
|
-
return getCrossPointWithCircle(point, direction, closestRadiusPoint!)
|
|
219
|
-
}
|
|
220
|
-
/* 求点在垂直或者水平方向上与圆形的交点 */
|
|
221
|
-
export const getCrossPointWithCircle = (
|
|
222
|
-
point: Point,
|
|
223
|
-
direction: Direction,
|
|
224
|
-
node: RadiusCircle,
|
|
225
|
-
): Point => {
|
|
226
|
-
let crossPoint: Point
|
|
227
|
-
const { x, y, r } = node
|
|
228
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
229
|
-
// 水平,x轴
|
|
230
|
-
const crossLeft = x - Math.sqrt(r * r - (point.y - y) * (point.y - y))
|
|
231
|
-
const crossRight = x + Math.sqrt(r * r - (point.y - y) * (point.y - y))
|
|
232
|
-
const crossX =
|
|
233
|
-
Math.abs(crossLeft - point.x) < Math.abs(crossRight - point.x)
|
|
234
|
-
? crossLeft
|
|
235
|
-
: crossRight
|
|
236
|
-
crossPoint = {
|
|
237
|
-
x: crossX,
|
|
238
|
-
y: point.y,
|
|
239
|
-
}
|
|
240
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
241
|
-
// 垂直,y轴
|
|
242
|
-
const crossTop = y - Math.sqrt(r * r - (point.x - x) * (point.x - x))
|
|
243
|
-
const crossBottom = y + Math.sqrt(r * r - (point.x - x) * (point.x - x))
|
|
244
|
-
const crossY =
|
|
245
|
-
Math.abs(crossTop - point.y) < Math.abs(crossBottom - point.y)
|
|
246
|
-
? crossTop
|
|
247
|
-
: crossBottom
|
|
248
|
-
crossPoint = {
|
|
249
|
-
x: point.x,
|
|
250
|
-
y: crossY,
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return crossPoint!
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/* 判断点所在边的方向 */
|
|
257
|
-
export const pointEdgeDirection = (
|
|
258
|
-
point: Point,
|
|
259
|
-
node: BaseNodeModel,
|
|
260
|
-
): Direction => {
|
|
261
|
-
const dx = Math.abs(point.x - node.x)
|
|
262
|
-
const dy = Math.abs(point.y - node.y)
|
|
263
|
-
return dx / node.width > dy / node.height
|
|
264
|
-
? SegmentDirection.VERTICAL
|
|
265
|
-
: SegmentDirection.HORIZONTAL
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// 判断矩形外框上一点是否在矩形直行线上
|
|
269
|
-
export const inStraightLineOfRect = (
|
|
270
|
-
point: Point,
|
|
271
|
-
node: BaseNodeModel,
|
|
272
|
-
): boolean => {
|
|
273
|
-
const rect = node as RectNodeModel
|
|
274
|
-
let isInStraight = false
|
|
275
|
-
const { x, y, width, height, radius } = rect
|
|
276
|
-
const rectBox = {
|
|
277
|
-
minX: x - width / 2 + radius,
|
|
278
|
-
maxX: x + width / 2 - radius,
|
|
279
|
-
minY: y - height / 2 + radius,
|
|
280
|
-
maxY: y + height / 2 - radius,
|
|
281
|
-
}
|
|
282
|
-
if (point.y === y + height / 2 || point.y === y - height / 2) {
|
|
283
|
-
isInStraight = point.x > rectBox.minX && point.x < rectBox.maxX
|
|
284
|
-
} else if (point.x === x + width / 2 || point.x === x - width / 2) {
|
|
285
|
-
isInStraight = point.y > rectBox.minY && point.y < rectBox.maxY
|
|
286
|
-
}
|
|
287
|
-
return isInStraight
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/* 求点在垂直或者水平方向上与椭圆的交点 */
|
|
291
|
-
export const getCrossPointWithEllipse = (
|
|
292
|
-
point: Point,
|
|
293
|
-
direction: Direction,
|
|
294
|
-
node: BaseNodeModel,
|
|
295
|
-
): Point => {
|
|
296
|
-
let crossPoint: Point
|
|
297
|
-
const { x, y, rx, ry } = node as EllipseNodeModel
|
|
298
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
299
|
-
// 水平
|
|
300
|
-
const crossLeft =
|
|
301
|
-
x -
|
|
302
|
-
Math.sqrt(rx * rx - ((point.y - y) * (point.y - y) * rx * rx) / (ry * ry))
|
|
303
|
-
const crossRight =
|
|
304
|
-
x +
|
|
305
|
-
Math.sqrt(rx * rx - ((point.y - y) * (point.y - y) * rx * rx) / (ry * ry))
|
|
306
|
-
const crossX =
|
|
307
|
-
Math.abs(crossLeft - point.x) < Math.abs(crossRight - point.x)
|
|
308
|
-
? crossLeft
|
|
309
|
-
: crossRight
|
|
310
|
-
crossPoint = {
|
|
311
|
-
x: crossX,
|
|
312
|
-
y: point.y,
|
|
313
|
-
}
|
|
314
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
315
|
-
// 垂直
|
|
316
|
-
const crossTop =
|
|
317
|
-
y -
|
|
318
|
-
Math.sqrt(ry * ry - ((point.x - x) * (point.x - x) * ry * ry) / (rx * rx))
|
|
319
|
-
const crossBottom =
|
|
320
|
-
y +
|
|
321
|
-
Math.sqrt(ry * ry - ((point.x - x) * (point.x - x) * ry * ry) / (rx * rx))
|
|
322
|
-
const crossY =
|
|
323
|
-
Math.abs(crossTop - point.y) < Math.abs(crossBottom - point.y)
|
|
324
|
-
? crossTop
|
|
325
|
-
: crossBottom
|
|
326
|
-
crossPoint = {
|
|
327
|
-
x: point.x,
|
|
328
|
-
y: crossY,
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
return crossPoint!
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/* 求点在垂直或者水平方向上与多边形的交点 */
|
|
335
|
-
export const getCrossPointWithPolygon = (
|
|
336
|
-
point: Point,
|
|
337
|
-
direction: Direction,
|
|
338
|
-
node: BaseNodeModel,
|
|
339
|
-
): Point => {
|
|
340
|
-
const { pointsPosition } = node as PolygonNodeModel
|
|
341
|
-
let minDistance = Number.MAX_SAFE_INTEGER
|
|
342
|
-
let crossPoint: Point
|
|
343
|
-
const segments: LineSegment[] = []
|
|
344
|
-
for (let i = 0; i < pointsPosition.length; i++) {
|
|
345
|
-
segments.push({
|
|
346
|
-
start: pointsPosition[i],
|
|
347
|
-
end: pointsPosition[(i + 1) % pointsPosition.length],
|
|
348
|
-
})
|
|
349
|
-
}
|
|
350
|
-
segments.forEach((item) => {
|
|
351
|
-
const { start, end } = item
|
|
352
|
-
let a = start
|
|
353
|
-
let b = end
|
|
354
|
-
if (start.x > end.x) {
|
|
355
|
-
a = end
|
|
356
|
-
b = start
|
|
357
|
-
}
|
|
358
|
-
let pointXY = {
|
|
359
|
-
x: point.x,
|
|
360
|
-
y: point.y,
|
|
361
|
-
}
|
|
362
|
-
// 如果多边形当前线段是垂直,求交点
|
|
363
|
-
if (a.x === b.x && direction === SegmentDirection.HORIZONTAL) {
|
|
364
|
-
pointXY = {
|
|
365
|
-
x: a.x,
|
|
366
|
-
y: point.y,
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
// 如果多边形当前线段是水平,求交点
|
|
370
|
-
if (a.y === b.y && direction === SegmentDirection.VERTICAL) {
|
|
371
|
-
pointXY = {
|
|
372
|
-
x: point.x,
|
|
373
|
-
y: a.y,
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
// 如果线段不是水平或者垂直, 使用向量方程进行计算
|
|
377
|
-
if (a.x !== b.x && a.y !== b.y) {
|
|
378
|
-
const k = (b.y - a.y) / (b.x - a.x)
|
|
379
|
-
const m = (a.x * b.y - b.x * a.y) / (a.x - b.x)
|
|
380
|
-
if (direction === SegmentDirection.HORIZONTAL) {
|
|
381
|
-
pointXY = {
|
|
382
|
-
x: (point.y - m) / k,
|
|
383
|
-
y: point.y,
|
|
384
|
-
}
|
|
385
|
-
} else if (direction === SegmentDirection.VERTICAL) {
|
|
386
|
-
pointXY = {
|
|
387
|
-
x: point.x,
|
|
388
|
-
y: k * point.x + m,
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
// 如果交点在线段上
|
|
393
|
-
const inSegment = isInSegment(pointXY, start, end)
|
|
394
|
-
if (inSegment) {
|
|
395
|
-
const currentDistance = distance(pointXY.x, pointXY.y, point.x, point.y)
|
|
396
|
-
if (currentDistance < minDistance) {
|
|
397
|
-
minDistance = currentDistance
|
|
398
|
-
crossPoint = pointXY
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
})
|
|
402
|
-
return crossPoint!
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// 规范节点初始化数据
|
|
406
|
-
export const pickNodeConfig = (data: NodeConfig): NodeConfig => {
|
|
407
|
-
const nodeData = pick(data, [
|
|
408
|
-
'id',
|
|
409
|
-
'type',
|
|
410
|
-
'x',
|
|
411
|
-
'y',
|
|
412
|
-
'text',
|
|
413
|
-
'label',
|
|
414
|
-
'properties',
|
|
415
|
-
'virtual', // 区域节点是否为dnd添加的虚拟节点
|
|
416
|
-
'rotate',
|
|
417
|
-
|
|
418
|
-
// TODO: 确认是否可以加到此处
|
|
419
|
-
'resizable',
|
|
420
|
-
'rotatable',
|
|
421
|
-
])
|
|
422
|
-
return nodeData
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* 基于节点的边,重新获取新的节点
|
|
427
|
-
*/
|
|
428
|
-
export const getNodeAnchorPosition = (
|
|
429
|
-
center: BaseNodeModel,
|
|
430
|
-
point: Point,
|
|
431
|
-
width: number,
|
|
432
|
-
height: number,
|
|
433
|
-
) => {
|
|
434
|
-
let { x, y } = center
|
|
435
|
-
if (point.x > center.x) {
|
|
436
|
-
x = center.x + width / 2
|
|
437
|
-
} else if (point.x < center.x) {
|
|
438
|
-
x = center.x - width / 2
|
|
439
|
-
}
|
|
440
|
-
if (point.y > center.y) {
|
|
441
|
-
y = center.y + height / 2
|
|
442
|
-
} else if (point.y < center.y) {
|
|
443
|
-
y = center.y - height / 2
|
|
444
|
-
}
|
|
445
|
-
return {
|
|
446
|
-
x,
|
|
447
|
-
y,
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/*********************************************************
|
|
452
|
-
* Text 节点文本相关工具函数
|
|
453
|
-
********************************************************/
|
|
454
|
-
// Text 相关节点工具函数
|
|
455
|
-
// TODO: 获取文案高度,设置自动换行,利用 dom 计算高度
|
|
456
|
-
// function getTextHeight(text: string, font: string): number {
|
|
457
|
-
// const span = document.createElement('span');
|
|
458
|
-
// span.textContent = text;
|
|
459
|
-
// span.style.font = font;
|
|
460
|
-
|
|
461
|
-
// const range = document.createRange();
|
|
462
|
-
// range.selectNodeContents(span);
|
|
463
|
-
|
|
464
|
-
// const rect = range.getBoundingClientRect();
|
|
465
|
-
// const height = rect.height;
|
|
466
|
-
|
|
467
|
-
// return height;
|
|
468
|
-
// }
|
|
469
|
-
|
|
470
|
-
// 获取文案高度,自动换行,利用 dom 计算高度
|
|
471
|
-
export const getHtmlTextHeight = ({
|
|
472
|
-
rows,
|
|
473
|
-
style,
|
|
474
|
-
rowsLength,
|
|
475
|
-
className,
|
|
476
|
-
}: {
|
|
477
|
-
rows: string[]
|
|
478
|
-
style: h.JSX.CSSProperties
|
|
479
|
-
rowsLength: number
|
|
480
|
-
className: string
|
|
481
|
-
}) => {
|
|
482
|
-
const dom = document.createElement('div')
|
|
483
|
-
dom.className = className
|
|
484
|
-
dom.style.fontSize = `${style.fontSize}`
|
|
485
|
-
dom.style.width = `${style.width}`
|
|
486
|
-
dom.style.lineHeight = `${style.lineHeight}`
|
|
487
|
-
dom.style.padding = `${style.padding}`
|
|
488
|
-
if (style.fontFamily) {
|
|
489
|
-
dom.style.fontFamily = `${style.fontFamily}`
|
|
490
|
-
}
|
|
491
|
-
if (rowsLength > 1) {
|
|
492
|
-
rows.forEach((row) => {
|
|
493
|
-
const rowDom = document.createElement('div')
|
|
494
|
-
rowDom.textContent = row
|
|
495
|
-
dom.appendChild(rowDom)
|
|
496
|
-
})
|
|
497
|
-
} else {
|
|
498
|
-
dom.textContent = rows[0]
|
|
499
|
-
}
|
|
500
|
-
document.body.appendChild(dom)
|
|
501
|
-
const height = dom.clientHeight
|
|
502
|
-
document.body.removeChild(dom)
|
|
503
|
-
return height
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// 获取文案高度,自动换行,利用dom计算高度
|
|
507
|
-
export const getSvgTextWidthHeight = ({
|
|
508
|
-
rows,
|
|
509
|
-
rowsLength,
|
|
510
|
-
fontSize,
|
|
511
|
-
}: {
|
|
512
|
-
rows: string[]
|
|
513
|
-
rowsLength: number
|
|
514
|
-
fontSize: number
|
|
515
|
-
}) => {
|
|
516
|
-
let longestBytes = 0
|
|
517
|
-
rows &&
|
|
518
|
-
rows.forEach((item) => {
|
|
519
|
-
const rowByteLength = getBytesLength(item)
|
|
520
|
-
longestBytes = rowByteLength > longestBytes ? rowByteLength : longestBytes
|
|
521
|
-
})
|
|
522
|
-
// 背景框宽度,最长一行字节数/2 * fontsize + 2
|
|
523
|
-
// 背景框宽度, 行数 * fontsize + 2
|
|
524
|
-
return {
|
|
525
|
-
width: Math.ceil(longestBytes / 2) * fontSize + fontSize / 4,
|
|
526
|
-
height: rowsLength * (fontSize + 2) + fontSize / 4,
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* @description 格式化边校验信息
|
|
532
|
-
*/
|
|
533
|
-
export const formatAnchorConnectValidateData = (
|
|
534
|
-
data: Model.ConnectRuleResult,
|
|
535
|
-
) => {
|
|
536
|
-
if (typeof data !== 'object') {
|
|
537
|
-
return {
|
|
538
|
-
isAllPass: !!data,
|
|
539
|
-
msg: data ? '' : '不允许连接',
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
return data
|
|
543
|
-
}
|
package/src/util/raf.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { createUuid } from './uuid'
|
|
2
|
-
|
|
3
|
-
const rafIdMap = new Map()
|
|
4
|
-
|
|
5
|
-
export const createRaf = (callback: () => void) => {
|
|
6
|
-
const rafId = createUuid()
|
|
7
|
-
|
|
8
|
-
function run() {
|
|
9
|
-
callback()
|
|
10
|
-
const eId = rafIdMap.get(rafId)
|
|
11
|
-
if (eId) {
|
|
12
|
-
const nId = window.requestAnimationFrame(run)
|
|
13
|
-
rafIdMap.set(rafId, nId)
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const id = window.requestAnimationFrame(run)
|
|
18
|
-
rafIdMap.set(rafId, id)
|
|
19
|
-
return rafId
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const cancelRaf = (rafId: string) => {
|
|
23
|
-
const eId = rafIdMap.get(rafId)
|
|
24
|
-
if (eId) {
|
|
25
|
-
window.cancelAnimationFrame(eId)
|
|
26
|
-
rafIdMap.delete(rafId)
|
|
27
|
-
}
|
|
28
|
-
}
|