@logicflow/core 2.2.0 → 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/dist/index.css +3 -2
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/LogicFlow.d.ts +9 -0
- package/es/LogicFlow.js +0 -1
- package/es/constant/index.d.ts +1 -1
- package/es/constant/index.js +1 -1
- package/es/constant/theme.d.ts +136 -0
- package/es/constant/theme.js +680 -0
- package/es/index.css +3 -2
- package/es/model/GraphModel.d.ts +10 -2
- package/es/model/GraphModel.js +48 -14
- package/es/model/TransformModel.js +9 -9
- package/es/model/edge/BaseEdgeModel.js +7 -2
- package/es/model/edge/PolylineEdgeModel.d.ts +7 -0
- package/es/model/edge/PolylineEdgeModel.js +136 -7
- package/es/model/node/BaseNodeModel.d.ts +12 -1
- package/es/model/node/BaseNodeModel.js +9 -2
- package/es/model/node/HtmlNodeModel.d.ts +12 -0
- package/es/model/node/HtmlNodeModel.js +19 -0
- package/es/model/node/PolygonNodeModel.js +3 -3
- package/es/options.d.ts +4 -2
- package/es/style/index.css +3 -2
- package/es/style/index.less +3 -2
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/tool/MultipleSelectTool.js +10 -5
- package/es/util/drag.js +0 -1
- package/es/util/edge.d.ts +40 -1
- package/es/util/edge.js +43 -9
- package/es/util/geometry.d.ts +8 -0
- package/es/util/geometry.js +79 -0
- package/es/util/theme.d.ts +2 -65
- package/es/util/theme.js +4 -281
- package/es/view/Anchor.d.ts +1 -0
- package/es/view/Anchor.js +24 -21
- package/es/view/Control.d.ts +5 -0
- package/es/view/Control.js +44 -57
- package/es/view/edge/BaseEdge.js +9 -0
- package/es/view/edge/PolylineEdge.js +13 -2
- package/es/view/node/BaseNode.d.ts +1 -0
- package/es/view/node/BaseNode.js +23 -11
- package/es/view/node/HtmlNode.js +2 -4
- package/es/view/overlay/CanvasOverlay.js +5 -2
- package/es/view/overlay/Grid.d.ts +12 -1
- package/es/view/overlay/Grid.js +85 -23
- package/es/view/overlay/OutlineOverlay.d.ts +1 -0
- package/es/view/overlay/OutlineOverlay.js +18 -17
- package/es/view/overlay/gridConfig.d.ts +46 -0
- package/es/view/overlay/gridConfig.js +99 -0
- package/es/view/shape/Polygon.d.ts +0 -7
- package/es/view/shape/Polygon.js +12 -43
- package/lib/LogicFlow.d.ts +9 -0
- package/lib/LogicFlow.js +0 -1
- package/lib/constant/index.d.ts +1 -1
- package/lib/constant/index.js +16 -2
- package/lib/constant/theme.d.ts +136 -0
- package/lib/constant/theme.js +683 -0
- package/lib/index.css +3 -2
- package/lib/model/GraphModel.d.ts +10 -2
- package/lib/model/GraphModel.js +49 -15
- package/lib/model/TransformModel.js +9 -9
- package/lib/model/edge/BaseEdgeModel.js +7 -2
- package/lib/model/edge/PolylineEdgeModel.d.ts +7 -0
- package/lib/model/edge/PolylineEdgeModel.js +136 -7
- package/lib/model/node/BaseNodeModel.d.ts +12 -1
- package/lib/model/node/BaseNodeModel.js +9 -2
- package/lib/model/node/HtmlNodeModel.d.ts +12 -0
- package/lib/model/node/HtmlNodeModel.js +19 -0
- package/lib/model/node/PolygonNodeModel.js +3 -3
- package/lib/options.d.ts +4 -2
- package/lib/style/index.css +3 -2
- package/lib/style/index.less +3 -2
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/tool/MultipleSelectTool.js +10 -5
- package/lib/util/drag.js +0 -1
- package/lib/util/edge.d.ts +40 -1
- package/lib/util/edge.js +43 -9
- package/lib/util/geometry.d.ts +8 -0
- package/lib/util/geometry.js +81 -1
- package/lib/util/theme.d.ts +2 -65
- package/lib/util/theme.js +15 -292
- package/lib/view/Anchor.d.ts +1 -0
- package/lib/view/Anchor.js +24 -21
- package/lib/view/Control.d.ts +5 -0
- package/lib/view/Control.js +44 -57
- package/lib/view/edge/BaseEdge.js +9 -0
- package/lib/view/edge/PolylineEdge.js +13 -2
- package/lib/view/node/BaseNode.d.ts +1 -0
- package/lib/view/node/BaseNode.js +22 -10
- package/lib/view/node/HtmlNode.js +1 -3
- package/lib/view/overlay/CanvasOverlay.js +5 -2
- package/lib/view/overlay/Grid.d.ts +12 -1
- package/lib/view/overlay/Grid.js +83 -21
- package/lib/view/overlay/OutlineOverlay.d.ts +1 -0
- package/lib/view/overlay/OutlineOverlay.js +18 -17
- package/lib/view/overlay/gridConfig.d.ts +46 -0
- package/lib/view/overlay/gridConfig.js +104 -0
- package/lib/view/shape/Polygon.d.ts +0 -7
- package/lib/view/shape/Polygon.js +13 -45
- 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 -1849
- 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 -2008
- 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/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 -1788
- 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 -777
- package/src/model/edge/BezierEdgeModel.ts +0 -197
- package/src/model/edge/LineEdgeModel.ts +0 -36
- package/src/model/edge/PolylineEdgeModel.ts +0 -672
- package/src/model/edge/index.ts +0 -4
- package/src/model/index.ts +0 -9
- package/src/model/node/BaseNodeModel.ts +0 -949
- 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 -50
- package/src/model/node/PolygonNodeModel.ts +0 -150
- 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 -145
- package/src/style/index.less +0 -261
- package/src/style/raw.ts +0 -220
- package/src/tool/MultipleSelectTool.tsx +0 -132
- 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 -220
- package/src/util/edge.ts +0 -1060
- package/src/util/geometry.ts +0 -55
- 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 -375
- 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 -445
- package/src/view/Control.tsx +0 -512
- 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 -650
- package/src/view/edge/BezierEdge.tsx +0 -101
- package/src/view/edge/LineEdge.tsx +0 -81
- package/src/view/edge/PolylineEdge.tsx +0 -299
- package/src/view/edge/index.ts +0 -6
- package/src/view/index.ts +0 -8
- package/src/view/node/BaseNode.tsx +0 -571
- 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 -95
- 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 -288
- package/src/view/overlay/Grid.tsx +0 -162
- package/src/view/overlay/ModificationOverlay.tsx +0 -31
- package/src/view/overlay/OutlineOverlay.tsx +0 -170
- 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/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 -91
- package/src/view/shape/Polyline.tsx +0 -31
- package/src/view/shape/Rect.tsx +0 -44
- package/src/view/shape/Text.tsx +0 -169
- 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/resize.ts
DELETED
|
@@ -1,606 +0,0 @@
|
|
|
1
|
-
import { ResizeControl, ResizeControlIndex } from '../view/Control'
|
|
2
|
-
import { cloneDeep, find, forEach } from 'lodash-es'
|
|
3
|
-
import { BaseNodeModel, GraphModel } from '../model'
|
|
4
|
-
import { EventType } from '../constant'
|
|
5
|
-
|
|
6
|
-
import ResizeInfo = ResizeControl.ResizeInfo
|
|
7
|
-
import ResizeNodeData = ResizeControl.ResizeNodeData
|
|
8
|
-
import {
|
|
9
|
-
calculatePointAfterRotateAngle,
|
|
10
|
-
getNewCenter,
|
|
11
|
-
radianToAngle,
|
|
12
|
-
} from '../algorithm/rotate'
|
|
13
|
-
import type { SimplePoint } from '../algorithm/rotate'
|
|
14
|
-
|
|
15
|
-
export function calculateWidthAndHeight(
|
|
16
|
-
startRotatedTouchControlPoint: SimplePoint,
|
|
17
|
-
endRotatedTouchControlPoint: SimplePoint,
|
|
18
|
-
oldCenter: SimplePoint,
|
|
19
|
-
angle: number,
|
|
20
|
-
freezeWidth = false,
|
|
21
|
-
freezeHeight = false,
|
|
22
|
-
oldWidth: number,
|
|
23
|
-
oldHeight: number,
|
|
24
|
-
) {
|
|
25
|
-
// 假设目前触摸的是右下角的control点
|
|
26
|
-
// 计算出来左上角的control坐标,resize过程左上角的control坐标保持不变
|
|
27
|
-
const freezePoint: SimplePoint = {
|
|
28
|
-
x: oldCenter.x - (startRotatedTouchControlPoint.x - oldCenter.x),
|
|
29
|
-
y: oldCenter.y - (startRotatedTouchControlPoint.y - oldCenter.y),
|
|
30
|
-
}
|
|
31
|
-
// 【touchEndPoint】右下角 + freezePoint左上角 计算出新的中心点
|
|
32
|
-
const newCenter = getNewCenter(freezePoint, endRotatedTouchControlPoint)
|
|
33
|
-
|
|
34
|
-
// 得到【touchEndPoint】右下角-没有transform的坐标
|
|
35
|
-
let endZeroTouchControlPoint: SimplePoint = calculatePointAfterRotateAngle(
|
|
36
|
-
endRotatedTouchControlPoint,
|
|
37
|
-
newCenter,
|
|
38
|
-
-angle,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
// ---------- 使用transform之前的坐标计算出新的width和height ----------
|
|
42
|
-
|
|
43
|
-
// 得到左上角---没有transform的坐标
|
|
44
|
-
let zeroFreezePoint: SimplePoint = calculatePointAfterRotateAngle(
|
|
45
|
-
freezePoint,
|
|
46
|
-
newCenter,
|
|
47
|
-
-angle,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
if (freezeWidth) {
|
|
51
|
-
// 如果固定width,那么不能单纯使用endZeroTouchControlPoint.x=startZeroTouchControlPoint.x
|
|
52
|
-
// 因为去掉transform的左上角不一定是重合的,我们要保证的是transform后的左上角重合
|
|
53
|
-
const newWidth = Math.abs(endZeroTouchControlPoint.x - zeroFreezePoint.x)
|
|
54
|
-
const widthDx = newWidth - oldWidth
|
|
55
|
-
|
|
56
|
-
// 点击的是左边锚点,是+widthDx/2,点击是右边锚点,是-widthDx/2
|
|
57
|
-
if (newCenter.x > endZeroTouchControlPoint.x) {
|
|
58
|
-
// 当前触摸的是左边锚点
|
|
59
|
-
newCenter.x = newCenter.x + widthDx / 2
|
|
60
|
-
} else {
|
|
61
|
-
// 当前触摸的是右边锚点
|
|
62
|
-
newCenter.x = newCenter.x - widthDx / 2
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
if (freezeHeight) {
|
|
66
|
-
const newHeight = Math.abs(endZeroTouchControlPoint.y - zeroFreezePoint.y)
|
|
67
|
-
const heightDy = newHeight - oldHeight
|
|
68
|
-
if (newCenter.y > endZeroTouchControlPoint.y) {
|
|
69
|
-
// 当前触摸的是上边锚点
|
|
70
|
-
newCenter.y = newCenter.y + heightDy / 2
|
|
71
|
-
} else {
|
|
72
|
-
newCenter.y = newCenter.y - heightDy / 2
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (freezeWidth || freezeHeight) {
|
|
77
|
-
// 如果调整过transform之前的坐标,那么transform后的坐标也会改变,那么算出来的newCenter也得调整
|
|
78
|
-
// 由于无论如何rotate,中心点都是不变的,因此我们可以使用transform之前的坐标算出新的中心点
|
|
79
|
-
const nowFreezePoint = calculatePointAfterRotateAngle(
|
|
80
|
-
zeroFreezePoint,
|
|
81
|
-
newCenter,
|
|
82
|
-
angle,
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
// 得到当前新rect的左上角与实际上transform后的左上角的偏移量
|
|
86
|
-
const dx = nowFreezePoint.x - freezePoint.x
|
|
87
|
-
const dy = nowFreezePoint.y - freezePoint.y
|
|
88
|
-
|
|
89
|
-
// 修正不使用transform的坐标: 左上角、右下角、center
|
|
90
|
-
newCenter.x = newCenter.x - dx
|
|
91
|
-
newCenter.y = newCenter.y - dy
|
|
92
|
-
zeroFreezePoint = calculatePointAfterRotateAngle(
|
|
93
|
-
freezePoint,
|
|
94
|
-
newCenter,
|
|
95
|
-
-angle,
|
|
96
|
-
)
|
|
97
|
-
endZeroTouchControlPoint = {
|
|
98
|
-
x: newCenter.x - (zeroFreezePoint.x - newCenter.x),
|
|
99
|
-
y: newCenter.y - (zeroFreezePoint.y - newCenter.y),
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// transform之前的坐标的左上角+右下角计算出宽度和高度
|
|
104
|
-
let width = Math.abs(endZeroTouchControlPoint.x - zeroFreezePoint.x)
|
|
105
|
-
let height = Math.abs(endZeroTouchControlPoint.y - zeroFreezePoint.y)
|
|
106
|
-
|
|
107
|
-
// ---------- 使用transform之前的坐标计算出新的width和height ----------
|
|
108
|
-
|
|
109
|
-
if (freezeWidth) {
|
|
110
|
-
// 理论计算出来的width应该等于oldWidth
|
|
111
|
-
// 但是有误差,比如oldWidth = 100; newWidth=100.000000000001
|
|
112
|
-
// 会在handleResize()限制放大缩小的最大最小范围中被阻止滑动
|
|
113
|
-
width = oldWidth
|
|
114
|
-
}
|
|
115
|
-
if (freezeHeight) {
|
|
116
|
-
height = oldHeight
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
width,
|
|
121
|
-
height,
|
|
122
|
-
center: newCenter,
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function recalcRotatedResizeInfo(
|
|
127
|
-
pct: number,
|
|
128
|
-
resizeInfo: ResizeInfo,
|
|
129
|
-
rotate: number,
|
|
130
|
-
controlX: number,
|
|
131
|
-
controlY: number,
|
|
132
|
-
oldCenterX: number,
|
|
133
|
-
oldCenterY: number,
|
|
134
|
-
freezeWidth = false,
|
|
135
|
-
freezeHeight = false,
|
|
136
|
-
) {
|
|
137
|
-
// 假设我们触摸的点是右下角的control
|
|
138
|
-
const { deltaX, deltaY, width: oldWidth, height: oldHeight } = resizeInfo
|
|
139
|
-
const angle = radianToAngle(rotate)
|
|
140
|
-
|
|
141
|
-
// 右下角的control
|
|
142
|
-
const startZeroTouchControlPoint = {
|
|
143
|
-
x: controlX, // control锚点的坐标x
|
|
144
|
-
y: controlY, // control锚点的坐标y
|
|
145
|
-
}
|
|
146
|
-
const oldCenter = { x: oldCenterX, y: oldCenterY }
|
|
147
|
-
// 右下角的control坐标(transform后的-touchStartPoint)
|
|
148
|
-
const startRotatedTouchControlPoint = calculatePointAfterRotateAngle(
|
|
149
|
-
startZeroTouchControlPoint,
|
|
150
|
-
oldCenter,
|
|
151
|
-
angle,
|
|
152
|
-
)
|
|
153
|
-
// 右下角的control坐标(transform后的-touchEndPoint)
|
|
154
|
-
const endRotatedTouchControlPoint = {
|
|
155
|
-
x: startRotatedTouchControlPoint.x + deltaX,
|
|
156
|
-
y: startRotatedTouchControlPoint.y + deltaY,
|
|
157
|
-
}
|
|
158
|
-
// 计算出新的宽度和高度以及新的中心点
|
|
159
|
-
const {
|
|
160
|
-
width: newWidth,
|
|
161
|
-
height: newHeight,
|
|
162
|
-
center: newCenter,
|
|
163
|
-
} = calculateWidthAndHeight(
|
|
164
|
-
startRotatedTouchControlPoint,
|
|
165
|
-
endRotatedTouchControlPoint,
|
|
166
|
-
oldCenter,
|
|
167
|
-
angle,
|
|
168
|
-
freezeWidth,
|
|
169
|
-
freezeHeight,
|
|
170
|
-
oldWidth,
|
|
171
|
-
oldHeight,
|
|
172
|
-
)
|
|
173
|
-
// calculateWidthAndHeight()得到的是整个宽度,比如圆pct=0.5,此时newWidth等于整个圆直径
|
|
174
|
-
resizeInfo.width = newWidth * pct
|
|
175
|
-
resizeInfo.height = newHeight * pct
|
|
176
|
-
|
|
177
|
-
// BaseNodeModel.resize(deltaX/2, deltaY/2),因此这里要*2
|
|
178
|
-
resizeInfo.deltaX = (newCenter.x - oldCenter.x) * 2
|
|
179
|
-
resizeInfo.deltaY = (newCenter.y - oldCenter.y) * 2
|
|
180
|
-
|
|
181
|
-
return resizeInfo
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* 计算 Control 拖动后,节点的高度信息
|
|
186
|
-
* @param index
|
|
187
|
-
* @param resizeInfo
|
|
188
|
-
* @param pct
|
|
189
|
-
* @param freezeWidth
|
|
190
|
-
* @param freezeHeight
|
|
191
|
-
*/
|
|
192
|
-
export const recalcResizeInfo = (
|
|
193
|
-
index: ResizeControlIndex,
|
|
194
|
-
resizeInfo: ResizeInfo,
|
|
195
|
-
pct = 1,
|
|
196
|
-
freezeWidth = false,
|
|
197
|
-
freezeHeight = false,
|
|
198
|
-
rotate = 0,
|
|
199
|
-
controlX: number | undefined,
|
|
200
|
-
controlY: number | undefined,
|
|
201
|
-
oldCenterX: number,
|
|
202
|
-
oldCenterY: number,
|
|
203
|
-
forceProportional = false,
|
|
204
|
-
): ResizeInfo => {
|
|
205
|
-
const nextResizeInfo = cloneDeep(resizeInfo)
|
|
206
|
-
let { deltaX, deltaY } = nextResizeInfo
|
|
207
|
-
const { width, height, PCTResizeInfo } = nextResizeInfo
|
|
208
|
-
|
|
209
|
-
if (PCTResizeInfo) {
|
|
210
|
-
const sensitivity = 4 // 越低越灵敏
|
|
211
|
-
let deltaScale = 0
|
|
212
|
-
let combineDelta = 0
|
|
213
|
-
switch (index) {
|
|
214
|
-
case ResizeControlIndex.LEFT_TOP:
|
|
215
|
-
combineDelta = (deltaX * -1 - deltaY) / sensitivity
|
|
216
|
-
break
|
|
217
|
-
case ResizeControlIndex.RIGHT_TOP:
|
|
218
|
-
combineDelta = (deltaX - deltaY) / sensitivity
|
|
219
|
-
break
|
|
220
|
-
case ResizeControlIndex.RIGHT_BOTTOM:
|
|
221
|
-
combineDelta = (deltaX + deltaY) / sensitivity
|
|
222
|
-
break
|
|
223
|
-
case ResizeControlIndex.LEFT_BOTTOM:
|
|
224
|
-
combineDelta = (deltaX * -1 + deltaY) / sensitivity
|
|
225
|
-
break
|
|
226
|
-
default:
|
|
227
|
-
break
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (combineDelta !== 0) {
|
|
231
|
-
deltaScale =
|
|
232
|
-
Math.round(
|
|
233
|
-
(combineDelta / PCTResizeInfo.ResizeBasis.basisHeight) * 100000,
|
|
234
|
-
) / 1000
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
PCTResizeInfo.ResizePCT.widthPCT = Math.max(
|
|
238
|
-
Math.min(
|
|
239
|
-
PCTResizeInfo.ResizePCT.widthPCT + deltaScale,
|
|
240
|
-
PCTResizeInfo.ScaleLimit.maxScaleLimit,
|
|
241
|
-
),
|
|
242
|
-
PCTResizeInfo.ScaleLimit.minScaleLimit,
|
|
243
|
-
)
|
|
244
|
-
PCTResizeInfo.ResizePCT.heightPCT = Math.max(
|
|
245
|
-
Math.min(
|
|
246
|
-
PCTResizeInfo.ResizePCT.heightPCT + deltaScale,
|
|
247
|
-
PCTResizeInfo.ScaleLimit.maxScaleLimit,
|
|
248
|
-
),
|
|
249
|
-
PCTResizeInfo.ScaleLimit.minScaleLimit,
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
const spcWidth = Math.round(
|
|
253
|
-
(PCTResizeInfo.ResizePCT.widthPCT *
|
|
254
|
-
PCTResizeInfo.ResizeBasis.basisWidth) /
|
|
255
|
-
100,
|
|
256
|
-
)
|
|
257
|
-
const spcHeight = Math.round(
|
|
258
|
-
(PCTResizeInfo.ResizePCT.heightPCT *
|
|
259
|
-
PCTResizeInfo.ResizeBasis.basisHeight) /
|
|
260
|
-
100,
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
switch (index) {
|
|
264
|
-
case ResizeControlIndex.LEFT_TOP:
|
|
265
|
-
deltaX = width - spcWidth
|
|
266
|
-
deltaY = height - spcHeight
|
|
267
|
-
break
|
|
268
|
-
case ResizeControlIndex.RIGHT_TOP:
|
|
269
|
-
deltaX = spcWidth - width
|
|
270
|
-
deltaY = height - spcHeight
|
|
271
|
-
break
|
|
272
|
-
case ResizeControlIndex.RIGHT_BOTTOM:
|
|
273
|
-
deltaX = spcWidth - width
|
|
274
|
-
deltaY = spcHeight - height
|
|
275
|
-
break
|
|
276
|
-
case ResizeControlIndex.LEFT_BOTTOM:
|
|
277
|
-
deltaX = width - spcWidth
|
|
278
|
-
deltaY = spcHeight - height
|
|
279
|
-
break
|
|
280
|
-
default:
|
|
281
|
-
break
|
|
282
|
-
}
|
|
283
|
-
return nextResizeInfo
|
|
284
|
-
}
|
|
285
|
-
if (
|
|
286
|
-
rotate % (2 * Math.PI) !== 0 &&
|
|
287
|
-
controlX !== undefined &&
|
|
288
|
-
controlY !== undefined
|
|
289
|
-
) {
|
|
290
|
-
// 角度rotate不为0,则触发另外的计算修正resize的deltaX和deltaY
|
|
291
|
-
// 因为rotate不为0的时候,左上角的坐标一直在变化
|
|
292
|
-
// 角度rotate不为0得到的resizeInfo.deltaX仅仅代表中心点的变化,而不是宽度的变化
|
|
293
|
-
return recalcRotatedResizeInfo(
|
|
294
|
-
pct,
|
|
295
|
-
nextResizeInfo,
|
|
296
|
-
rotate,
|
|
297
|
-
controlX,
|
|
298
|
-
controlY,
|
|
299
|
-
oldCenterX,
|
|
300
|
-
oldCenterY,
|
|
301
|
-
freezeWidth,
|
|
302
|
-
freezeHeight,
|
|
303
|
-
)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
//Shift键等比缩放逻辑
|
|
307
|
-
if (forceProportional) {
|
|
308
|
-
// 计算当前的宽高比
|
|
309
|
-
const aspectRatio = width / height
|
|
310
|
-
|
|
311
|
-
// 根据拖拽方向确定主要的缩放参考
|
|
312
|
-
let primaryDelta = 0
|
|
313
|
-
let newWidth = width
|
|
314
|
-
let newHeight = height
|
|
315
|
-
|
|
316
|
-
switch (index) {
|
|
317
|
-
case ResizeControlIndex.LEFT_TOP:
|
|
318
|
-
// 取绝对值较大的delta作为主要缩放参考
|
|
319
|
-
primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? -deltaX : -deltaY
|
|
320
|
-
if (aspectRatio >= 1) {
|
|
321
|
-
// 宽度大于等于高度,以宽度为基准
|
|
322
|
-
newWidth = width + primaryDelta
|
|
323
|
-
newHeight = newWidth / aspectRatio
|
|
324
|
-
} else {
|
|
325
|
-
// 高度大于宽度,以高度为基准
|
|
326
|
-
newHeight = height + primaryDelta
|
|
327
|
-
newWidth = newHeight * aspectRatio
|
|
328
|
-
}
|
|
329
|
-
nextResizeInfo.width = newWidth
|
|
330
|
-
nextResizeInfo.height = newHeight
|
|
331
|
-
nextResizeInfo.deltaX = width - newWidth
|
|
332
|
-
nextResizeInfo.deltaY = height - newHeight
|
|
333
|
-
break
|
|
334
|
-
|
|
335
|
-
case ResizeControlIndex.RIGHT_TOP:
|
|
336
|
-
primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? deltaX : -deltaY
|
|
337
|
-
if (aspectRatio >= 1) {
|
|
338
|
-
newWidth = width + primaryDelta
|
|
339
|
-
newHeight = newWidth / aspectRatio
|
|
340
|
-
} else {
|
|
341
|
-
newHeight = height - primaryDelta
|
|
342
|
-
newWidth = newHeight * aspectRatio
|
|
343
|
-
}
|
|
344
|
-
nextResizeInfo.width = newWidth
|
|
345
|
-
nextResizeInfo.height = newHeight
|
|
346
|
-
nextResizeInfo.deltaX = newWidth - width
|
|
347
|
-
nextResizeInfo.deltaY = height - newHeight
|
|
348
|
-
break
|
|
349
|
-
|
|
350
|
-
case ResizeControlIndex.RIGHT_BOTTOM:
|
|
351
|
-
primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? deltaX : deltaY
|
|
352
|
-
if (aspectRatio >= 1) {
|
|
353
|
-
newWidth = width + primaryDelta
|
|
354
|
-
newHeight = newWidth / aspectRatio
|
|
355
|
-
} else {
|
|
356
|
-
newHeight = height + primaryDelta
|
|
357
|
-
newWidth = newHeight * aspectRatio
|
|
358
|
-
}
|
|
359
|
-
nextResizeInfo.width = newWidth
|
|
360
|
-
nextResizeInfo.height = newHeight
|
|
361
|
-
nextResizeInfo.deltaX = newWidth - width
|
|
362
|
-
nextResizeInfo.deltaY = newHeight - height
|
|
363
|
-
break
|
|
364
|
-
|
|
365
|
-
case ResizeControlIndex.LEFT_BOTTOM:
|
|
366
|
-
primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? -deltaX : deltaY
|
|
367
|
-
if (aspectRatio >= 1) {
|
|
368
|
-
newWidth = width - primaryDelta
|
|
369
|
-
newHeight = newWidth / aspectRatio
|
|
370
|
-
} else {
|
|
371
|
-
newHeight = height + primaryDelta
|
|
372
|
-
newWidth = newHeight * aspectRatio
|
|
373
|
-
}
|
|
374
|
-
nextResizeInfo.width = newWidth
|
|
375
|
-
nextResizeInfo.height = newHeight
|
|
376
|
-
nextResizeInfo.deltaX = width - newWidth
|
|
377
|
-
nextResizeInfo.deltaY = newHeight - height
|
|
378
|
-
break
|
|
379
|
-
|
|
380
|
-
default:
|
|
381
|
-
break
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return nextResizeInfo
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// 原有的非等比缩放逻辑保持不变
|
|
388
|
-
switch (index) {
|
|
389
|
-
case ResizeControlIndex.LEFT_TOP:
|
|
390
|
-
nextResizeInfo.width = freezeWidth ? width : width - deltaX * pct
|
|
391
|
-
nextResizeInfo.height = freezeHeight ? height : height - deltaY * pct
|
|
392
|
-
break
|
|
393
|
-
case ResizeControlIndex.RIGHT_TOP:
|
|
394
|
-
nextResizeInfo.width = freezeWidth ? width : width + deltaX * pct
|
|
395
|
-
nextResizeInfo.height = freezeHeight ? height : height - deltaY * pct
|
|
396
|
-
break
|
|
397
|
-
case ResizeControlIndex.RIGHT_BOTTOM:
|
|
398
|
-
nextResizeInfo.width = freezeWidth ? width : width + deltaX * pct
|
|
399
|
-
nextResizeInfo.height = freezeHeight ? height : height + deltaY * pct
|
|
400
|
-
break
|
|
401
|
-
case ResizeControlIndex.LEFT_BOTTOM:
|
|
402
|
-
nextResizeInfo.width = freezeWidth ? width : width - deltaX * pct
|
|
403
|
-
nextResizeInfo.height = freezeHeight ? height : height + deltaY * pct
|
|
404
|
-
break
|
|
405
|
-
default:
|
|
406
|
-
break
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
return nextResizeInfo
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
export const updateEdgePointByAnchors = (
|
|
413
|
-
nodeModel: BaseNodeModel,
|
|
414
|
-
graphModel: GraphModel,
|
|
415
|
-
) => {
|
|
416
|
-
// https://github.com/didi/LogicFlow/issues/807
|
|
417
|
-
// https://github.com/didi/LogicFlow/issues/875
|
|
418
|
-
// 之前的做法,比如Rect是使用getRectResizeEdgePoint()计算边的point缩放后的位置
|
|
419
|
-
// getRectResizeEdgePoint()考虑了瞄点在四条边以及在4个圆角的情况
|
|
420
|
-
// 使用的是一种等比例缩放的模式,比如:
|
|
421
|
-
// const pct = (y - beforeNode.y) / (beforeNode.height / 2 - radius)
|
|
422
|
-
// afterPoint.y = afterNode.y + (afterNode.height / 2 - radius) * pct
|
|
423
|
-
// 但是用户自定义的getDefaultAnchor()不一定是按照比例编写的
|
|
424
|
-
// 它可能是 x: x + 20:每次缩放都会保持在x右边20的位置,因此用户自定义瞄点时,然后产生无法跟随的问题
|
|
425
|
-
// 现在的做法是:直接获取用户自定义瞄点的位置,然后用这个位置作为边的新的起点,而不是自己进行计算
|
|
426
|
-
const { id, anchors } = nodeModel
|
|
427
|
-
const edges = graphModel.getNodeEdges(id)
|
|
428
|
-
// 更新边
|
|
429
|
-
forEach(edges, (edge) => {
|
|
430
|
-
if (edge.sourceNodeId === id) {
|
|
431
|
-
// 边是以该节点为 sourceNode 时
|
|
432
|
-
const anchorItem = find(
|
|
433
|
-
anchors,
|
|
434
|
-
(anchor) => anchor.id === edge.sourceAnchorId,
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
if (anchorItem) {
|
|
438
|
-
edge.updateStartPoint({
|
|
439
|
-
x: anchorItem.x,
|
|
440
|
-
y: anchorItem.y,
|
|
441
|
-
})
|
|
442
|
-
}
|
|
443
|
-
} else if (edge.targetNodeId === id) {
|
|
444
|
-
// 边是以该节点为 targetNode 时
|
|
445
|
-
const anchorItem = find(
|
|
446
|
-
anchors,
|
|
447
|
-
(anchor) => anchor.id === edge.targetAnchorId,
|
|
448
|
-
)
|
|
449
|
-
|
|
450
|
-
if (anchorItem) {
|
|
451
|
-
edge.updateEndPoint({
|
|
452
|
-
x: anchorItem.x,
|
|
453
|
-
y: anchorItem.y,
|
|
454
|
-
})
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
})
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
export const triggerResizeEvent = (
|
|
461
|
-
preNodeData: ResizeNodeData,
|
|
462
|
-
curNodeData: ResizeNodeData,
|
|
463
|
-
deltaX: number,
|
|
464
|
-
deltaY: number,
|
|
465
|
-
index: number,
|
|
466
|
-
nodeModel: BaseNodeModel,
|
|
467
|
-
graphModel: GraphModel,
|
|
468
|
-
) => {
|
|
469
|
-
graphModel.eventCenter.emit(EventType.NODE_RESIZE, {
|
|
470
|
-
preData: preNodeData,
|
|
471
|
-
data: curNodeData,
|
|
472
|
-
deltaX,
|
|
473
|
-
deltaY,
|
|
474
|
-
index,
|
|
475
|
-
model: nodeModel,
|
|
476
|
-
})
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// TODO:确认 handleResize 函数的类型定义
|
|
480
|
-
export type IHandleResizeParams = {
|
|
481
|
-
x?: number
|
|
482
|
-
y?: number
|
|
483
|
-
deltaX: number
|
|
484
|
-
deltaY: number
|
|
485
|
-
index: ResizeControlIndex
|
|
486
|
-
nodeModel: BaseNodeModel
|
|
487
|
-
graphModel: GraphModel
|
|
488
|
-
cancelCallback?: () => void
|
|
489
|
-
forceProportional?: boolean
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
/**
|
|
493
|
-
* 处理节点的 resize 事件,提出来放到 utils 中,方便在外面(extension)中使用
|
|
494
|
-
* @param x
|
|
495
|
-
* @param y
|
|
496
|
-
* @param deltaX
|
|
497
|
-
* @param deltaY
|
|
498
|
-
* @param index
|
|
499
|
-
* @param nodeModel
|
|
500
|
-
* @param graphModel
|
|
501
|
-
* @param cancelCallback
|
|
502
|
-
* @param forceProportional
|
|
503
|
-
*/
|
|
504
|
-
export const handleResize = ({
|
|
505
|
-
x,
|
|
506
|
-
y,
|
|
507
|
-
deltaX,
|
|
508
|
-
deltaY,
|
|
509
|
-
index,
|
|
510
|
-
nodeModel,
|
|
511
|
-
graphModel,
|
|
512
|
-
cancelCallback,
|
|
513
|
-
forceProportional = false,
|
|
514
|
-
}: IHandleResizeParams) => {
|
|
515
|
-
const {
|
|
516
|
-
r, // circle
|
|
517
|
-
rx, // ellipse/diamond
|
|
518
|
-
ry,
|
|
519
|
-
width, // rect/html
|
|
520
|
-
height,
|
|
521
|
-
PCTResizeInfo,
|
|
522
|
-
|
|
523
|
-
minWidth,
|
|
524
|
-
minHeight,
|
|
525
|
-
maxWidth,
|
|
526
|
-
maxHeight,
|
|
527
|
-
rotate,
|
|
528
|
-
x: oldCenterX,
|
|
529
|
-
y: oldCenterY,
|
|
530
|
-
} = nodeModel
|
|
531
|
-
|
|
532
|
-
const isFreezeWidth = minWidth === maxWidth
|
|
533
|
-
const isFreezeHeight = minHeight === maxHeight
|
|
534
|
-
|
|
535
|
-
const resizeInfo = {
|
|
536
|
-
width: r || rx || width,
|
|
537
|
-
height: r || ry || height,
|
|
538
|
-
deltaX,
|
|
539
|
-
deltaY,
|
|
540
|
-
PCTResizeInfo,
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
const pct = r || (rx && ry) ? 1 / 2 : 1
|
|
544
|
-
const controlX = x
|
|
545
|
-
const controlY = y
|
|
546
|
-
const nextSize = recalcResizeInfo(
|
|
547
|
-
index,
|
|
548
|
-
resizeInfo,
|
|
549
|
-
pct,
|
|
550
|
-
isFreezeWidth,
|
|
551
|
-
isFreezeHeight,
|
|
552
|
-
rotate,
|
|
553
|
-
controlX,
|
|
554
|
-
controlY,
|
|
555
|
-
oldCenterX,
|
|
556
|
-
oldCenterY,
|
|
557
|
-
forceProportional,
|
|
558
|
-
)
|
|
559
|
-
|
|
560
|
-
// 限制放大缩小的最大最小范围
|
|
561
|
-
if (
|
|
562
|
-
nextSize.width < minWidth ||
|
|
563
|
-
nextSize.width > maxWidth ||
|
|
564
|
-
nextSize.height < minHeight ||
|
|
565
|
-
nextSize.height > maxHeight
|
|
566
|
-
) {
|
|
567
|
-
// this.dragHandler.cancelDrag()
|
|
568
|
-
cancelCallback?.()
|
|
569
|
-
return
|
|
570
|
-
}
|
|
571
|
-
if (
|
|
572
|
-
rotate % (2 * Math.PI) == 0 ||
|
|
573
|
-
PCTResizeInfo ||
|
|
574
|
-
controlX === undefined ||
|
|
575
|
-
controlY === undefined
|
|
576
|
-
) {
|
|
577
|
-
// rotate!==0并且不是PCTResizeInfo时,即使是isFreezeWidth||isFreezeHeight
|
|
578
|
-
// recalcRotatedResizeInfo()计算出来的中心点会发生变化
|
|
579
|
-
|
|
580
|
-
// 如果限制了宽高不变,对应的 x/y 不产生位移
|
|
581
|
-
nextSize.deltaX = isFreezeWidth ? 0 : nextSize.deltaX
|
|
582
|
-
nextSize.deltaY = isFreezeHeight ? 0 : nextSize.deltaY
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
const preNodeData = nodeModel.getData()
|
|
586
|
-
const curNodeData = nodeModel.resize(nextSize)
|
|
587
|
-
|
|
588
|
-
// 检测preNodeData和curNodeData是否没变化
|
|
589
|
-
if (preNodeData.x === curNodeData.x && preNodeData.y === curNodeData.y) {
|
|
590
|
-
// 中心点x和y都没有变化,说明无法resize,阻止下面边的更新以及resize事件的emit
|
|
591
|
-
return
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
// 更新边
|
|
595
|
-
updateEdgePointByAnchors(nodeModel, graphModel)
|
|
596
|
-
// 触发 resize 事件
|
|
597
|
-
triggerResizeEvent(
|
|
598
|
-
preNodeData,
|
|
599
|
-
curNodeData,
|
|
600
|
-
deltaX,
|
|
601
|
-
deltaY,
|
|
602
|
-
index,
|
|
603
|
-
nodeModel,
|
|
604
|
-
graphModel,
|
|
605
|
-
)
|
|
606
|
-
}
|
package/src/util/sampling.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { distance } from './node'
|
|
2
|
-
import LogicFlow from '../LogicFlow'
|
|
3
|
-
|
|
4
|
-
import Point = LogicFlow.Point
|
|
5
|
-
import Vector = LogicFlow.Vector
|
|
6
|
-
|
|
7
|
-
const SAMPLING_FREQUENCY = 100
|
|
8
|
-
const normal: Vector = {
|
|
9
|
-
x: 1,
|
|
10
|
-
y: 0,
|
|
11
|
-
z: 0,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 采样三次贝塞尔曲线上的点, 假设采样频率为SAMPLING_FREQUENCY, 取倒数第1-6/SAMPLING_FREQUENCY个点即t=1-6/SAMPLING_FREQUENCY
|
|
15
|
-
export function sampleCubic(
|
|
16
|
-
p1: Point,
|
|
17
|
-
cp1: Point,
|
|
18
|
-
cp2: Point,
|
|
19
|
-
p2: Point,
|
|
20
|
-
offset: number,
|
|
21
|
-
) {
|
|
22
|
-
const program = (t: number) => {
|
|
23
|
-
if (t < 0 || t > 1) {
|
|
24
|
-
throw new RangeError('The value range of parameter "t" is [0,1]')
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
x:
|
|
28
|
-
p1.x * (1 - t) ** 3 +
|
|
29
|
-
3 * cp1.x * t * (1 - t) ** 2 +
|
|
30
|
-
3 * cp2.x * t ** 2 * (1 - t) +
|
|
31
|
-
p2.x * t ** 3,
|
|
32
|
-
y:
|
|
33
|
-
p1.y * (1 - t) ** 3 +
|
|
34
|
-
3 * cp1.y * t * (1 - t) ** 2 +
|
|
35
|
-
3 * cp2.y * t ** 2 * (1 - t) +
|
|
36
|
-
p2.y * t ** 3,
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// fix: https://github.com/didi/LogicFlow/issues/951
|
|
40
|
-
// 计算贝塞尔曲线上与终点距离为offset的点,作为箭头的的垂点。
|
|
41
|
-
let arrowDistance = 0
|
|
42
|
-
let t = 2
|
|
43
|
-
const { x: x1, y: y1 } = p2
|
|
44
|
-
let point = p2
|
|
45
|
-
while (arrowDistance < offset && t < 50) {
|
|
46
|
-
point = program(1 - t / SAMPLING_FREQUENCY)
|
|
47
|
-
const { x: x2, y: y2 } = point
|
|
48
|
-
arrowDistance = distance(x1, y1, x2, y2)
|
|
49
|
-
t++
|
|
50
|
-
}
|
|
51
|
-
return point
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function crossByZ(v: Vector, v1: Vector) {
|
|
55
|
-
return v.x * v1.y - v.y * v1.x
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function dot(v: Vector, w: Vector) {
|
|
59
|
-
const v1 = [v.x, v.y, v.z]
|
|
60
|
-
const v2 = [w.x, w.y, w.z]
|
|
61
|
-
return v2.reduce((prev, cur, index) => prev + cur * v1[index])
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function angle(v1: Vector, v2: Vector) {
|
|
65
|
-
const negative = crossByZ(v1, v2)
|
|
66
|
-
const r = Math.acos(dot(normalize(v1), normalize(v2)))
|
|
67
|
-
return negative >= 0 ? r : -r
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function normalize(v: Vector): Vector {
|
|
71
|
-
const len = Math.hypot(v.x, v.y)
|
|
72
|
-
return {
|
|
73
|
-
x: v.x / len,
|
|
74
|
-
y: v.y / len,
|
|
75
|
-
z: 0,
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function getThetaOfVector(v: Vector) {
|
|
80
|
-
return angle(normal, v)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function degrees(radians: number) {
|
|
84
|
-
return radians * (180 / Math.PI)
|
|
85
|
-
}
|