@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.
Files changed (236) hide show
  1. package/dist/index.css +3 -2
  2. package/dist/index.min.js +1 -1
  3. package/dist/index.min.js.map +1 -1
  4. package/es/LogicFlow.d.ts +9 -0
  5. package/es/LogicFlow.js +0 -1
  6. package/es/constant/index.d.ts +1 -1
  7. package/es/constant/index.js +1 -1
  8. package/es/constant/theme.d.ts +136 -0
  9. package/es/constant/theme.js +680 -0
  10. package/es/index.css +3 -2
  11. package/es/model/GraphModel.d.ts +10 -2
  12. package/es/model/GraphModel.js +48 -14
  13. package/es/model/TransformModel.js +9 -9
  14. package/es/model/edge/BaseEdgeModel.js +7 -2
  15. package/es/model/edge/PolylineEdgeModel.d.ts +7 -0
  16. package/es/model/edge/PolylineEdgeModel.js +136 -7
  17. package/es/model/node/BaseNodeModel.d.ts +12 -1
  18. package/es/model/node/BaseNodeModel.js +9 -2
  19. package/es/model/node/HtmlNodeModel.d.ts +12 -0
  20. package/es/model/node/HtmlNodeModel.js +19 -0
  21. package/es/model/node/PolygonNodeModel.js +3 -3
  22. package/es/options.d.ts +4 -2
  23. package/es/style/index.css +3 -2
  24. package/es/style/index.less +3 -2
  25. package/es/style/raw.d.ts +1 -1
  26. package/es/style/raw.js +1 -1
  27. package/es/tool/MultipleSelectTool.js +10 -5
  28. package/es/util/drag.js +0 -1
  29. package/es/util/edge.d.ts +40 -1
  30. package/es/util/edge.js +43 -9
  31. package/es/util/geometry.d.ts +8 -0
  32. package/es/util/geometry.js +79 -0
  33. package/es/util/theme.d.ts +2 -65
  34. package/es/util/theme.js +4 -281
  35. package/es/view/Anchor.d.ts +1 -0
  36. package/es/view/Anchor.js +24 -21
  37. package/es/view/Control.d.ts +5 -0
  38. package/es/view/Control.js +44 -57
  39. package/es/view/edge/BaseEdge.js +9 -0
  40. package/es/view/edge/PolylineEdge.js +13 -2
  41. package/es/view/node/BaseNode.d.ts +1 -0
  42. package/es/view/node/BaseNode.js +23 -11
  43. package/es/view/node/HtmlNode.js +2 -4
  44. package/es/view/overlay/CanvasOverlay.js +5 -2
  45. package/es/view/overlay/Grid.d.ts +12 -1
  46. package/es/view/overlay/Grid.js +85 -23
  47. package/es/view/overlay/OutlineOverlay.d.ts +1 -0
  48. package/es/view/overlay/OutlineOverlay.js +18 -17
  49. package/es/view/overlay/gridConfig.d.ts +46 -0
  50. package/es/view/overlay/gridConfig.js +99 -0
  51. package/es/view/shape/Polygon.d.ts +0 -7
  52. package/es/view/shape/Polygon.js +12 -43
  53. package/lib/LogicFlow.d.ts +9 -0
  54. package/lib/LogicFlow.js +0 -1
  55. package/lib/constant/index.d.ts +1 -1
  56. package/lib/constant/index.js +16 -2
  57. package/lib/constant/theme.d.ts +136 -0
  58. package/lib/constant/theme.js +683 -0
  59. package/lib/index.css +3 -2
  60. package/lib/model/GraphModel.d.ts +10 -2
  61. package/lib/model/GraphModel.js +49 -15
  62. package/lib/model/TransformModel.js +9 -9
  63. package/lib/model/edge/BaseEdgeModel.js +7 -2
  64. package/lib/model/edge/PolylineEdgeModel.d.ts +7 -0
  65. package/lib/model/edge/PolylineEdgeModel.js +136 -7
  66. package/lib/model/node/BaseNodeModel.d.ts +12 -1
  67. package/lib/model/node/BaseNodeModel.js +9 -2
  68. package/lib/model/node/HtmlNodeModel.d.ts +12 -0
  69. package/lib/model/node/HtmlNodeModel.js +19 -0
  70. package/lib/model/node/PolygonNodeModel.js +3 -3
  71. package/lib/options.d.ts +4 -2
  72. package/lib/style/index.css +3 -2
  73. package/lib/style/index.less +3 -2
  74. package/lib/style/raw.d.ts +1 -1
  75. package/lib/style/raw.js +1 -1
  76. package/lib/tool/MultipleSelectTool.js +10 -5
  77. package/lib/util/drag.js +0 -1
  78. package/lib/util/edge.d.ts +40 -1
  79. package/lib/util/edge.js +43 -9
  80. package/lib/util/geometry.d.ts +8 -0
  81. package/lib/util/geometry.js +81 -1
  82. package/lib/util/theme.d.ts +2 -65
  83. package/lib/util/theme.js +15 -292
  84. package/lib/view/Anchor.d.ts +1 -0
  85. package/lib/view/Anchor.js +24 -21
  86. package/lib/view/Control.d.ts +5 -0
  87. package/lib/view/Control.js +44 -57
  88. package/lib/view/edge/BaseEdge.js +9 -0
  89. package/lib/view/edge/PolylineEdge.js +13 -2
  90. package/lib/view/node/BaseNode.d.ts +1 -0
  91. package/lib/view/node/BaseNode.js +22 -10
  92. package/lib/view/node/HtmlNode.js +1 -3
  93. package/lib/view/overlay/CanvasOverlay.js +5 -2
  94. package/lib/view/overlay/Grid.d.ts +12 -1
  95. package/lib/view/overlay/Grid.js +83 -21
  96. package/lib/view/overlay/OutlineOverlay.d.ts +1 -0
  97. package/lib/view/overlay/OutlineOverlay.js +18 -17
  98. package/lib/view/overlay/gridConfig.d.ts +46 -0
  99. package/lib/view/overlay/gridConfig.js +104 -0
  100. package/lib/view/shape/Polygon.d.ts +0 -7
  101. package/lib/view/shape/Polygon.js +13 -45
  102. package/package.json +6 -1
  103. package/.turbo/turbo-build$colon$dev.log +0 -10
  104. package/.turbo/turbo-build.log +0 -33
  105. package/CHANGELOG.md +0 -1849
  106. package/__tests__/algorithm/egde.test.ts +0 -131
  107. package/__tests__/algorithm/index.test.ts +0 -74
  108. package/__tests__/algorithm/outline.test.ts +0 -43
  109. package/__tests__/bugs/1545-spec.test.ts +0 -42
  110. package/__tests__/event/event.test.ts +0 -22
  111. package/__tests__/history/history.test.ts +0 -28
  112. package/__tests__/logicflow.test.ts +0 -575
  113. package/__tests__/model/graphmodel.test.ts +0 -87
  114. package/__tests__/util/compatible.test.ts +0 -48
  115. package/__tests__/util/edge.test.ts +0 -224
  116. package/__tests__/util/geometry.test.ts +0 -14
  117. package/__tests__/util/graph.test.ts +0 -16
  118. package/__tests__/util/matrix.test.ts +0 -41
  119. package/__tests__/util/node.test.ts +0 -68
  120. package/__tests__/util/sampling.test.ts +0 -12
  121. package/__tests__/util/vector.test.ts +0 -50
  122. package/__tests__/util/zIndex.test.ts +0 -10
  123. package/src/LogicFlow.tsx +0 -2008
  124. package/src/algorithm/edge.ts +0 -67
  125. package/src/algorithm/index.ts +0 -70
  126. package/src/algorithm/outline.ts +0 -77
  127. package/src/algorithm/rotate.ts +0 -55
  128. package/src/common/drag.ts +0 -219
  129. package/src/common/history.ts +0 -108
  130. package/src/common/index.ts +0 -6
  131. package/src/common/keyboard.ts +0 -108
  132. package/src/common/matrix.ts +0 -122
  133. package/src/common/vector.ts +0 -93
  134. package/src/constant/index.ts +0 -179
  135. package/src/event/event.md +0 -66
  136. package/src/event/eventArgs.ts +0 -643
  137. package/src/event/eventEmitter.ts +0 -156
  138. package/src/history/index.ts +0 -119
  139. package/src/index.less +0 -1
  140. package/src/index.ts +0 -26
  141. package/src/keyboard/index.ts +0 -112
  142. package/src/keyboard/shortcut.ts +0 -200
  143. package/src/model/BaseModel.ts +0 -250
  144. package/src/model/EditConfigModel.ts +0 -334
  145. package/src/model/GraphModel.ts +0 -1788
  146. package/src/model/NestedTransformModel.ts +0 -121
  147. package/src/model/SnaplineModel.ts +0 -256
  148. package/src/model/TransformModel.ts +0 -258
  149. package/src/model/edge/BaseEdgeModel.ts +0 -777
  150. package/src/model/edge/BezierEdgeModel.ts +0 -197
  151. package/src/model/edge/LineEdgeModel.ts +0 -36
  152. package/src/model/edge/PolylineEdgeModel.ts +0 -672
  153. package/src/model/edge/index.ts +0 -4
  154. package/src/model/index.ts +0 -9
  155. package/src/model/node/BaseNodeModel.ts +0 -949
  156. package/src/model/node/CircleNodeModel.ts +0 -91
  157. package/src/model/node/DiamondNodeModel.ts +0 -132
  158. package/src/model/node/EllipseNodeModel.ts +0 -98
  159. package/src/model/node/HtmlNodeModel.ts +0 -50
  160. package/src/model/node/PolygonNodeModel.ts +0 -150
  161. package/src/model/node/RectNodeModel.ts +0 -69
  162. package/src/model/node/TextNodeModel.ts +0 -54
  163. package/src/model/node/index.ts +0 -8
  164. package/src/options.ts +0 -145
  165. package/src/style/index.less +0 -261
  166. package/src/style/raw.ts +0 -220
  167. package/src/tool/MultipleSelectTool.tsx +0 -132
  168. package/src/tool/TextEditTool.tsx +0 -193
  169. package/src/tool/index.ts +0 -101
  170. package/src/typings.d.ts +0 -5
  171. package/src/util/animation.ts +0 -29
  172. package/src/util/browser.ts +0 -4
  173. package/src/util/compatible.ts +0 -15
  174. package/src/util/drag.ts +0 -220
  175. package/src/util/edge.ts +0 -1060
  176. package/src/util/geometry.ts +0 -55
  177. package/src/util/graph.ts +0 -46
  178. package/src/util/index.ts +0 -17
  179. package/src/util/matrix.ts +0 -129
  180. package/src/util/mobx.ts +0 -23
  181. package/src/util/node.ts +0 -543
  182. package/src/util/raf.ts +0 -28
  183. package/src/util/resize.ts +0 -606
  184. package/src/util/sampling.ts +0 -85
  185. package/src/util/theme.ts +0 -375
  186. package/src/util/uuid.ts +0 -26
  187. package/src/util/vector.ts +0 -93
  188. package/src/util/zIndex.ts +0 -6
  189. package/src/view/Anchor.tsx +0 -445
  190. package/src/view/Control.tsx +0 -512
  191. package/src/view/Graph.tsx +0 -141
  192. package/src/view/Rotate.tsx +0 -113
  193. package/src/view/behavior/dnd.ts +0 -162
  194. package/src/view/behavior/index.ts +0 -2
  195. package/src/view/behavior/snapline.ts +0 -16
  196. package/src/view/edge/AdjustPoint.tsx +0 -425
  197. package/src/view/edge/Arrow.tsx +0 -54
  198. package/src/view/edge/BaseEdge.tsx +0 -650
  199. package/src/view/edge/BezierEdge.tsx +0 -101
  200. package/src/view/edge/LineEdge.tsx +0 -81
  201. package/src/view/edge/PolylineEdge.tsx +0 -299
  202. package/src/view/edge/index.ts +0 -6
  203. package/src/view/index.ts +0 -8
  204. package/src/view/node/BaseNode.tsx +0 -571
  205. package/src/view/node/CircleNode.tsx +0 -21
  206. package/src/view/node/DiamondNode.tsx +0 -24
  207. package/src/view/node/EllipseNode.tsx +0 -22
  208. package/src/view/node/HtmlNode.tsx +0 -95
  209. package/src/view/node/PolygonNode.tsx +0 -28
  210. package/src/view/node/RectNode.tsx +0 -30
  211. package/src/view/node/TextNode.tsx +0 -39
  212. package/src/view/node/index.ts +0 -8
  213. package/src/view/overlay/BackgroundOverlay.tsx +0 -34
  214. package/src/view/overlay/BezierAdjustOverlay.tsx +0 -150
  215. package/src/view/overlay/CanvasOverlay.tsx +0 -288
  216. package/src/view/overlay/Grid.tsx +0 -162
  217. package/src/view/overlay/ModificationOverlay.tsx +0 -31
  218. package/src/view/overlay/OutlineOverlay.tsx +0 -170
  219. package/src/view/overlay/SnaplineOverlay.tsx +0 -44
  220. package/src/view/overlay/ToolOverlay.tsx +0 -65
  221. package/src/view/overlay/getTransformHoc.tsx +0 -50
  222. package/src/view/overlay/index.ts +0 -8
  223. package/src/view/shape/Circle.tsx +0 -41
  224. package/src/view/shape/Ellipse.tsx +0 -42
  225. package/src/view/shape/Line.tsx +0 -39
  226. package/src/view/shape/Path.tsx +0 -22
  227. package/src/view/shape/Polygon.tsx +0 -91
  228. package/src/view/shape/Polyline.tsx +0 -31
  229. package/src/view/shape/Rect.tsx +0 -44
  230. package/src/view/shape/Text.tsx +0 -169
  231. package/src/view/shape/index.ts +0 -8
  232. package/src/view/text/BaseText.tsx +0 -134
  233. package/src/view/text/LineText.tsx +0 -168
  234. package/src/view/text/index.ts +0 -2
  235. package/stats.html +0 -4842
  236. package/tsconfig.json +0 -18
@@ -1,949 +0,0 @@
1
- import { action, computed, isObservable, observable, toJS } from 'mobx'
2
- import {
3
- assign,
4
- cloneDeep,
5
- has,
6
- isNil,
7
- mapKeys,
8
- isUndefined,
9
- set,
10
- } from 'lodash-es'
11
- import { GraphModel, Model } from '..'
12
- import LogicFlow from '../../LogicFlow'
13
- import {
14
- createUuid,
15
- formatData,
16
- getClosestAnchor,
17
- getZIndex,
18
- Matrix,
19
- pickNodeConfig,
20
- TranslateMatrix,
21
- } from '../../util'
22
- import {
23
- ElementState,
24
- ElementType,
25
- EventType,
26
- ModelType,
27
- OverlapMode,
28
- TextMode,
29
- } from '../../constant'
30
- import { ResizeControl } from '../../view/Control'
31
- import AnchorConfig = Model.AnchorConfig
32
- import GraphElements = LogicFlow.GraphElements
33
- import TextConfig = LogicFlow.TextConfig
34
- import NodeConfig = LogicFlow.NodeConfig
35
- import NodeData = LogicFlow.NodeData
36
- import Point = LogicFlow.Point
37
- import CommonTheme = LogicFlow.CommonTheme
38
- import PropertiesType = LogicFlow.PropertiesType
39
-
40
- import ResizeInfo = ResizeControl.ResizeInfo
41
- import ResizeNodeData = ResizeControl.ResizeNodeData
42
- import PCTResizeParams = ResizeControl.PCTResizeParams
43
-
44
- export interface IBaseNodeModel<P extends PropertiesType>
45
- extends Model.BaseModel<P> {
46
- /**
47
- * model基础类型,固定为node
48
- */
49
- readonly BaseType: ElementType.NODE
50
- properties: P
51
-
52
- isDragging: boolean
53
- isShowAnchor: boolean
54
- getNodeStyle: () => CommonTheme
55
- getTextStyle: () => LogicFlow.TextNodeTheme
56
- setIsShowAnchor: (isShowAnchor: boolean) => void
57
- }
58
-
59
- export class BaseNodeModel<P extends PropertiesType = PropertiesType>
60
- implements IBaseNodeModel<P>
61
- {
62
- readonly BaseType = ElementType.NODE
63
- static BaseType: ElementType = ElementType.NODE
64
-
65
- // 数据属性
66
- public id = ''
67
- @observable readonly type = ''
68
- @observable x = 0
69
- @observable y = 0
70
- @observable textMode = TextMode.TEXT
71
- @observable text: TextConfig = {
72
- value: '',
73
- x: 0,
74
- y: 0,
75
- draggable: false,
76
- editable: true,
77
- }
78
- @observable properties: P
79
- // 形状属性
80
- @observable private _width = 100
81
- public get width() {
82
- return this._width
83
- }
84
-
85
- public set width(value: number) {
86
- this._width = value
87
- }
88
-
89
- @observable private _height = 80
90
- public get height() {
91
- return this._height
92
- }
93
-
94
- public set height(value: number) {
95
- this._height = value
96
- }
97
-
98
- minWidth: number = 30
99
- minHeight: number = 30
100
- maxWidth: number = 2000
101
- maxHeight: number = 2000
102
- PCTResizeInfo?: PCTResizeParams
103
-
104
- // 根据与 (x, y) 的偏移量计算 anchors 的坐标
105
- @observable anchorsOffset: BaseNodeModel.AnchorsOffsetItem[] = []
106
-
107
- // 状态属性
108
- readonly virtual: boolean = false
109
- @observable isSelected = false
110
- @observable isHovered = false
111
- @observable isShowAnchor = false
112
- @observable isDragging = false
113
- @observable isHitable = true // TODO: 兼容拼写错误的情况 Remove
114
- @observable isHittable = true // 细粒度控制节点是否对用户操作进行反应
115
- @observable draggable = true
116
- @observable visible = true
117
-
118
- @observable rotatable = true // 节点可旋转
119
- @observable resizable = true // 节点可缩放
120
-
121
- // 其它属性
122
- graphModel: GraphModel
123
- @observable zIndex = 1
124
- @observable state = ElementState.DEFAULT
125
- @observable autoToFront = true // 节点选中时是否自动置顶,默认为true.
126
- @observable style: CommonTheme = {} // 每个节点自己的样式,动态修改
127
-
128
- // TODO: 利用向量计算实现 平移、旋转、缩放 等操作,利用 svg 的 transform 属性
129
- @observable transform!: string // 节点的transform属性
130
- @observable private _rotate = 0
131
- get rotate() {
132
- return this._rotate
133
- }
134
-
135
- set rotate(value: number) {
136
- this._rotate = value
137
- const { x = 0, y = 0 } = this
138
- this.transform = new TranslateMatrix(-x, -y)
139
- .rotate(value)
140
- .translate(x, y)
141
- .toString()
142
- }
143
-
144
- modelType = ModelType.NODE
145
- additionStateData?: Model.AdditionStateDataType = {}
146
-
147
- // 节点连入、练出、移动等规则
148
- targetRules: Model.ConnectRule[] = []
149
- sourceRules: Model.ConnectRule[] = []
150
- moveRules: Model.NodeMoveRule[] = [] // 节点移动之前的hook
151
- resizeRules: Model.NodeResizeRule[] = [] // 节点resize之前的hook
152
- hasSetTargetRules = false // 用来限制rules的重复值
153
- hasSetSourceRules = false; // 用来限制rules的重复值
154
- [propName: string]: any // 支持用户自定义属性
155
-
156
- constructor(data: NodeConfig<P>, graphModel: GraphModel) {
157
- this.graphModel = graphModel
158
- this.properties = data.properties ?? ({} as P)
159
-
160
- this.initNodeData(data)
161
- this.setAttributes()
162
- }
163
-
164
- /**
165
- * 获取进入当前节点的边和节点
166
- */
167
- @computed get incoming(): GraphElements {
168
- return {
169
- nodes: this.graphModel.getNodeIncomingNode(this.id),
170
- edges: this.graphModel.getNodeIncomingEdge(this.id),
171
- }
172
- }
173
-
174
- /*
175
- * 获取离开当前节点的边和节点
176
- */
177
- @computed get outgoing(): GraphElements {
178
- return {
179
- nodes: this.graphModel.getNodeOutgoingNode(this.id),
180
- edges: this.graphModel.getNodeOutgoingEdge(this.id),
181
- }
182
- }
183
-
184
- /**
185
- * @overridable 可以重写
186
- * 初始化节点数据
187
- * initNodeData 和 setAttributes 的区别在于
188
- * initNodeData 只在节点初始化的时候调用,用于初始化节点的所有属性。
189
- * setAttributes 除了初始化调用外,还会在 properties 发生变化了调用。
190
- */
191
- public initNodeData(data: NodeConfig) {
192
- if (!data.properties) {
193
- data.properties = {}
194
- }
195
-
196
- if (!data.id) {
197
- // 自定义节点id > 全局定义id > 内置
198
- const { idGenerator } = this.graphModel
199
- const globalId = idGenerator && idGenerator(data.type)
200
- const nodeId = this.createId()
201
- data.id = nodeId || globalId || createUuid()
202
- }
203
-
204
- this.formatText(data)
205
- // 在下面又将 NodeConfig 中的数据赋值给了 this,应该会触发 setAttributes,确认是否符合预期
206
- // TODO: 确认 constructor 中赋值 properties 是否必要,此处将 NodeConfig 中所有属性赋值给 this,包括 rotate、rotatable,resizable 等
207
- assign(this, pickNodeConfig(data))
208
-
209
- const { overlapMode, eventCenter } = this.graphModel
210
- this.updateZIndexByOverlap(overlapMode, data.zIndex || getZIndex())
211
- eventCenter.on('overlap:change', (data) => {
212
- const { overlapMode: newMode } = data
213
- this.updateZIndexByOverlap(newMode, this.zIndex || getZIndex())
214
- })
215
- }
216
-
217
- /**
218
- * 设置model属性,每次properties发生变化会触发
219
- * 例如设置节点的宽度
220
- * @example
221
- *
222
- * setAttributes () {
223
- * this.width = 300
224
- * this.height = 200
225
- * }
226
- *
227
- * @overridable 支持重写
228
- */
229
- public setAttributes() {}
230
-
231
- /**
232
- * @overridable 支持重写,自定义此类型节点默认生成方式
233
- * @returns string | null
234
- */
235
- public createId(): string | null {
236
- return null
237
- }
238
-
239
- /**
240
- * 设置当前元素的文本模式
241
- * @param mode
242
- */
243
- @action setTextMode(mode: TextMode) {
244
- this.textMode = mode
245
- }
246
-
247
- /**
248
- * 始化文本属性
249
- */
250
- private formatText(data: NodeConfig): void {
251
- const {
252
- editConfigModel: { nodeTextDraggable, nodeTextEdit },
253
- } = this.graphModel
254
- const { x, y, text } = data
255
- let textConfig: TextConfig = {
256
- value: '',
257
- x,
258
- y,
259
- draggable: nodeTextDraggable,
260
- editable: nodeTextEdit,
261
- }
262
- if (text) {
263
- if (typeof text === 'string') {
264
- textConfig.value = text
265
- } else {
266
- textConfig = {
267
- ...textConfig,
268
- x: text.x ?? x,
269
- y: text.y ?? y,
270
- value: text.value ?? '',
271
- }
272
- if (!isUndefined(text.draggable)) {
273
- textConfig.draggable = text.draggable
274
- }
275
- if (!isUndefined(text.editable)) {
276
- textConfig.editable = text.editable
277
- }
278
- }
279
- }
280
-
281
- data.text = textConfig
282
- }
283
-
284
- /**
285
- * @overridable 支持重写
286
- * 计算节点 resize 时
287
- */
288
- resize(resizeInfo: ResizeInfo): ResizeNodeData {
289
- const { width, height, deltaX, deltaY } = resizeInfo
290
-
291
- const isAllowResize = this.isAllowResizeNode(deltaX, deltaY, width, height)
292
-
293
- if (!isAllowResize) {
294
- return this.getData()
295
- }
296
-
297
- // 移动节点以及文本内容
298
- this.move(deltaX / 2, deltaY / 2)
299
-
300
- this.width = width
301
- this.height = height
302
- this.setProperties({
303
- width,
304
- height,
305
- })
306
- return this.getData()
307
- }
308
-
309
- // TODO: 等比例缩放
310
- proportionalResize() {}
311
-
312
- /**
313
- * 获取被保存时返回的数据
314
- * @overridable 支持重写
315
- */
316
- getData(): NodeData {
317
- const { x, y, value } = this.text
318
- let { properties } = this
319
- if (isObservable(properties)) {
320
- properties = toJS(properties)
321
- }
322
- if (isNil(properties.width)) {
323
- // resize()的时候会触发this.setProperties({width,height})
324
- // 然后返回getData(),可以从properties拿到width
325
- // 但是初始化如果没有在properties传入width,那么getData()就一直无法从properties拿到width
326
- properties.width = this.width
327
- }
328
- if (isNil(properties.height)) {
329
- // resize()的时候会触发this.setProperties({width,height})
330
- // 然后返回getData(),可以从properties拿到height
331
- // 但是初始化如果没有在properties传入height,那么getData()就一直无法从properties拿到width
332
- properties.height = this.height
333
- }
334
- const data: NodeData = {
335
- id: this.id,
336
- type: this.type,
337
- x: this.x,
338
- y: this.y,
339
- properties,
340
- }
341
- if (this.rotate) {
342
- data.rotate = this.rotate
343
- }
344
- // 因为默认模式和节点在上模式下,对边的zIndex要求不高(因为渲染的时候会按照模式对所有元素进行排序)
345
- // 所以只在递增模式和静态模式下设置zIndex
346
- if (
347
- [OverlapMode.INCREASE, OverlapMode.STATIC].includes(
348
- this.graphModel.overlapMode,
349
- )
350
- ) {
351
- data.zIndex = this.zIndex
352
- }
353
- if (value) {
354
- data.text = {
355
- x,
356
- y,
357
- value,
358
- }
359
- }
360
- return data
361
- }
362
-
363
- /**
364
- * 用于在历史记录时获取节点数据,
365
- * 在某些情况下,如果希望某个属性变化不引起history的变化,
366
- * 可以重写此方法。
367
- */
368
- getHistoryData(): NodeData {
369
- return this.getData()
370
- }
371
-
372
- /**
373
- * 获取当前节点的properties
374
- */
375
- getProperties() {
376
- return toJS(this.properties)
377
- }
378
-
379
- /**
380
- * @overridable 支持重写
381
- * 获取当前节点最外层g标签Attributes, 例如 className
382
- * @returns 自定义节点样式
383
- */
384
- getOuterGAttributes(): LogicFlow.DomAttributes {
385
- return {
386
- className: '',
387
- }
388
- }
389
-
390
- /**
391
- * @overridable 支持重写
392
- * 获取当前节点样式
393
- * @returns 自定义节点样式
394
- */
395
- getNodeStyle(): CommonTheme {
396
- return {
397
- ...this.graphModel.theme.baseNode,
398
- ...this.style,
399
- }
400
- }
401
-
402
- /**
403
- * @overridable 支持重写
404
- * 获取当前节点文本样式
405
- */
406
- getTextStyle() {
407
- // 透传 nodeText
408
- const { nodeText } = this.graphModel.theme
409
- const { textStyle = {} } = this.properties
410
- return {
411
- ...cloneDeep(nodeText),
412
- ...cloneDeep(textStyle),
413
- }
414
- }
415
-
416
- /**
417
- * @overridable 支持重写
418
- * 获取当前节点旋转控制点的样式
419
- */
420
- getRotateControlStyle(): CommonTheme {
421
- const { rotateControl } = this.graphModel.theme
422
- return cloneDeep(rotateControl)
423
- }
424
-
425
- /**
426
- * @overrideable 支持重写
427
- * 获取当前节点缩放控制节点的样式
428
- */
429
- getResizeControlStyle() {
430
- const { resizeControl } = this.graphModel.theme
431
- return cloneDeep(resizeControl)
432
- }
433
-
434
- getResizeOutlineStyle() {
435
- const { resizeOutline } = this.graphModel.theme
436
- return cloneDeep(resizeOutline)
437
- }
438
-
439
- /**
440
- * @overridable 支持重写
441
- * 获取当前节点锚点样式
442
- * @returns 自定义样式
443
- */
444
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
445
- getAnchorStyle(_anchorInfo?: Point): LogicFlow.AnchorTheme {
446
- const { anchor } = this.graphModel.theme
447
- // 防止被重写覆盖主题。
448
- return cloneDeep(anchor)
449
- }
450
-
451
- /**
452
- * @overridable 支持重写
453
- * 获取当前节点锚点拖出连线样式
454
- * @returns 自定义锚点拖出样式
455
- */
456
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
457
- getAnchorLineStyle(_anchorInfo?: Point): LogicFlow.AnchorLineTheme {
458
- const { anchorLine } = this.graphModel.theme
459
- return cloneDeep(anchorLine)
460
- }
461
-
462
- /**
463
- * @overridable 支持重写
464
- * 获取outline样式,重写可以定义此类型节点outline样式, 默认使用主题样式
465
- * @returns 自定义outline样式
466
- */
467
- getOutlineStyle(): LogicFlow.OutlineTheme {
468
- const { outline } = this.graphModel.theme
469
- return cloneDeep(outline)
470
- }
471
-
472
- /**
473
- * @overridable 在连接边时,是否允许这个节点为 source 节点,边到 target 节点
474
- * @param target 目标节点
475
- * @param sourceAnchor 源锚点
476
- * @param targetAnchor 目标锚点
477
- * @param edgeId 调整后边的 id,在开启 adjustEdgeStartAndEnd 后调整边连接的节点时会传入
478
- * 详见:https://github.com/didi/LogicFlow/issues/926#issuecomment-1371823306
479
- */
480
- isAllowConnectedAsSource(
481
- target: BaseNodeModel,
482
- sourceAnchor?: Model.AnchorConfig,
483
- targetAnchor?: Model.AnchorConfig,
484
- edgeId?: string,
485
- ): Model.ConnectRuleResult {
486
- const rules = !this.hasSetSourceRules
487
- ? this.getConnectedSourceRules()
488
- : this.sourceRules
489
- this.hasSetSourceRules = true
490
- let isAllPass = true
491
- let msg: string = ''
492
- for (let i = 0; i < rules.length; i++) {
493
- const rule = rules[i]
494
- if (
495
- !rule.validate.call(
496
- this,
497
- this,
498
- target,
499
- sourceAnchor,
500
- targetAnchor,
501
- edgeId,
502
- )
503
- ) {
504
- isAllPass = false
505
- msg = rule.message
506
- break
507
- }
508
- }
509
- return {
510
- isAllPass,
511
- msg,
512
- }
513
- }
514
-
515
- /**
516
- * 获取当前节点作为连接的起始节点规则。
517
- */
518
- getConnectedSourceRules(): Model.ConnectRule[] {
519
- return this.sourceRules
520
- }
521
-
522
- /**
523
- * @overridable 在连线时,判断是否允许这个节点为 target 节点
524
- * @param source 源节点
525
- * @param sourceAnchor 源锚点
526
- * @param targetAnchor 目标锚点
527
- * @param edgeId 调整后边的 id,在开启 adjustEdgeStartAndEnd 后调整边连接的节点时会传入
528
- * 详见:https://github.com/didi/LogicFlow/issues/926#issuecomment-1371823306
529
- */
530
- isAllowConnectedAsTarget(
531
- source: BaseNodeModel,
532
- sourceAnchor?: Model.AnchorConfig,
533
- targetAnchor?: Model.AnchorConfig,
534
- edgeId?: string,
535
- ): Model.ConnectRuleResult {
536
- const rules = !this.hasSetTargetRules
537
- ? this.getConnectedTargetRules()
538
- : this.targetRules
539
- this.hasSetTargetRules = true
540
- let isAllPass = true
541
- let msg: string = ''
542
- for (let i = 0; i < rules.length; i++) {
543
- const rule = rules[i]
544
- if (
545
- !rule.validate.call(
546
- this,
547
- source,
548
- this,
549
- sourceAnchor,
550
- targetAnchor,
551
- edgeId,
552
- )
553
- ) {
554
- isAllPass = false
555
- msg = rule.message
556
- break
557
- }
558
- }
559
- return {
560
- isAllPass,
561
- msg,
562
- }
563
- }
564
-
565
- /**
566
- * 内部方法
567
- * 是否允许移动节点到新的位置
568
- */
569
- isAllowMoveNode(deltaX: number, deltaY: number): boolean | Model.IsAllowMove {
570
- let isAllowMoveX = true
571
- let isAllowMoveY = true
572
- const rules = this.moveRules.concat(this.graphModel.nodeMoveRules)
573
- for (const rule of rules) {
574
- const r = rule(this, deltaX, deltaY)
575
- if (!r) return false
576
- if (typeof r === 'object') {
577
- const r1 = r as Model.IsAllowMove
578
- if (!r1.x && !r1.y) {
579
- return false
580
- }
581
- isAllowMoveX = isAllowMoveX && r1.x
582
- isAllowMoveY = isAllowMoveY && r1.y
583
- }
584
- }
585
- return {
586
- x: isAllowMoveX,
587
- y: isAllowMoveY,
588
- }
589
- }
590
-
591
- /**
592
- * 获取作为连线终点时的所有规则。
593
- */
594
- getConnectedTargetRules(): Model.ConnectRule[] {
595
- return this.targetRules
596
- }
597
-
598
- /**
599
- * @returns Point[] 锚点坐标构成的数组
600
- */
601
- getAnchorsByOffset(): Model.AnchorConfig[] {
602
- const { anchorsOffset, id, x, y } = this
603
- if (anchorsOffset && anchorsOffset.length > 0) {
604
- return anchorsOffset.map((el, idx) => {
605
- if (el.length) {
606
- el = el as LogicFlow.PointTuple // 历史数据格式
607
- return {
608
- id: `${id}_${idx}`,
609
- x: x + el[0],
610
- y: y + el[1],
611
- }
612
- }
613
- el = el as Model.AnchorConfig
614
- return {
615
- ...el,
616
- x: x + el.x,
617
- y: y + el.y,
618
- id: el.id || `${id}_${idx}`,
619
- }
620
- })
621
- }
622
- return this.getDefaultAnchor()
623
- }
624
-
625
- /**
626
- * @overridable 子类重写此方法设置默认锚点
627
- * 获取节点默认情况下的锚点
628
- */
629
- public getDefaultAnchor(): Model.AnchorConfig[] {
630
- return []
631
- }
632
-
633
- /**
634
- * @overridable 子类重写此方法获取手动连接边到节点时,需要连接的锚点
635
- * 手动连接边到节点时,需要连接的锚点
636
- */
637
- public getTargetAnchor(position: Point): Model.AnchorInfo {
638
- return getClosestAnchor(position, this)
639
- }
640
-
641
- /**
642
- * 获取节点BBox
643
- */
644
- public getBounds(): Model.BoxBoundsPoint {
645
- return {
646
- minX: this.x - this.width / 2,
647
- minY: this.y - this.height / 2,
648
- maxX: this.x + this.width / 2,
649
- maxY: this.y + this.height / 2,
650
- }
651
- }
652
-
653
- get anchors(): Model.AnchorConfig[] {
654
- const anchors = this.getAnchorsByOffset()
655
- const { x, y, rotate } = this
656
- anchors.forEach((anchor) => {
657
- const { x: anchorX, y: anchorY } = anchor
658
- const [e, f] = new Matrix([anchorX, anchorY, 1])
659
- .translate(-x, -y)
660
- .rotate(rotate)
661
- .translate(x, y)[0]
662
- anchor.x = e
663
- anchor.y = f
664
- })
665
- return anchors
666
- }
667
-
668
- getAnchorInfo(anchorId: string | undefined): AnchorConfig | undefined {
669
- if (isNil(anchorId)) return undefined
670
-
671
- for (let i = 0; i < this.anchors.length; i++) {
672
- const anchor = this.anchors[i]
673
- if (anchor.id === anchorId) {
674
- return anchor
675
- }
676
- }
677
- }
678
-
679
- @action addNodeMoveRules(fn: Model.NodeMoveRule) {
680
- if (!this.moveRules.includes(fn)) {
681
- this.moveRules.push(fn)
682
- }
683
- }
684
-
685
- isAllowMoveByXORY(deltaX: number, deltaY: number, isIgnoreRule: boolean) {
686
- let isAllowMoveX: boolean
687
- let isAllowMoveY: boolean
688
- if (isIgnoreRule) {
689
- isAllowMoveX = true
690
- isAllowMoveY = true
691
- } else {
692
- const r = this.isAllowMoveNode(deltaX, deltaY)
693
- if (typeof r === 'boolean') {
694
- isAllowMoveX = r
695
- isAllowMoveY = r
696
- } else {
697
- isAllowMoveX = r.x
698
- isAllowMoveY = r.y
699
- }
700
- }
701
- return {
702
- isAllowMoveX,
703
- isAllowMoveY,
704
- }
705
- }
706
-
707
- @action move(deltaX: number, deltaY: number, isIgnoreRule = false): boolean {
708
- const { isAllowMoveX, isAllowMoveY } = this.isAllowMoveByXORY(
709
- deltaX,
710
- deltaY,
711
- isIgnoreRule,
712
- )
713
- if (isAllowMoveX) {
714
- this.x = this.x + deltaX
715
- this.text && this.moveText(deltaX, 0)
716
- }
717
- if (isAllowMoveY) {
718
- this.y = this.y + deltaY
719
- this.text && this.moveText(0, deltaY)
720
- }
721
- if (isAllowMoveX || isAllowMoveY) {
722
- // 更新x和y的同时也要更新对应的transform旋转矩阵(依赖x、y)
723
- this.rotate = this._rotate
724
- }
725
- return isAllowMoveX || isAllowMoveY
726
- }
727
-
728
- @action getMoveDistance(
729
- deltaX: number,
730
- deltaY: number,
731
- isIgnoreRule = false,
732
- ): [number, number] {
733
- const { isAllowMoveX, isAllowMoveY } = this.isAllowMoveByXORY(
734
- deltaX,
735
- deltaY,
736
- isIgnoreRule,
737
- )
738
- let moveX = 0
739
- let moveY = 0
740
-
741
- if (isAllowMoveX && deltaX) {
742
- this.x = this.x + deltaX
743
- this.text && this.moveText(deltaX, 0)
744
- moveX = deltaX
745
- }
746
- if (isAllowMoveY && deltaY) {
747
- this.y = this.y + deltaY
748
- this.text && this.moveText(0, deltaY)
749
- moveY = deltaY
750
- }
751
- this.transform = new TranslateMatrix(-this.x, -this.y)
752
- .rotate(this.rotate)
753
- .translate(this.x, this.y)
754
- .toString()
755
- return [moveX, moveY]
756
- }
757
-
758
- @action moveTo(x: number, y: number, isIgnoreRule = false): boolean {
759
- const deltaX = x - this.x
760
- const deltaY = y - this.y
761
- if (!isIgnoreRule && !this.isAllowMoveNode(deltaX, deltaY)) return false
762
-
763
- this.text && this.moveText(deltaX, deltaY)
764
- this.x = x
765
- this.y = y
766
- return true
767
- }
768
-
769
- @action moveText(deltaX: number, deltaY: number): void {
770
- const { x, y, value, draggable, editable } = this.text
771
- this.text = {
772
- value,
773
- editable,
774
- draggable,
775
- x: x + deltaX,
776
- y: y + deltaY,
777
- }
778
- }
779
-
780
- @action updateText(value: string): void {
781
- this.text = {
782
- ...toJS(this.text),
783
- value,
784
- }
785
- }
786
-
787
- @action addNodeResizeRules(fn: Model.NodeResizeRule) {
788
- if (!this.resizeRules.includes(fn)) {
789
- this.resizeRules.push(fn)
790
- }
791
- }
792
-
793
- /**
794
- * 内部方法
795
- * 是否允许resize节点到新的位置
796
- */
797
- isAllowResizeNode(
798
- deltaX: number,
799
- deltaY: number,
800
- width: number,
801
- height: number,
802
- ): boolean {
803
- const rules = this.resizeRules.concat(this.graphModel.nodeResizeRules)
804
- for (const rule of rules) {
805
- const r = rule(this, deltaX, deltaY, width, height)
806
- if (!r) return false
807
- }
808
- return true
809
- }
810
-
811
- @action setSelected(flag = true): void {
812
- this.isSelected = flag
813
- }
814
-
815
- @action setHovered(flag = true): void {
816
- this.isHovered = flag
817
- this.setIsShowAnchor(flag)
818
- }
819
-
820
- @action setIsShowAnchor(flag = true): void {
821
- this.isShowAnchor = flag
822
- }
823
-
824
- @action setRotatable(flag = true): void {
825
- this.rotatable = flag
826
- }
827
-
828
- @action setResizable(flag = true): void {
829
- this.resizable = flag
830
- }
831
-
832
- @action setHitable(flag = true): void {
833
- this.isHitable = flag
834
- }
835
-
836
- @action setHittable(flag = true): void {
837
- this.isHittable = flag
838
- }
839
-
840
- @action setElementState(
841
- state: number,
842
- additionStateData?: Model.AdditionStateDataType,
843
- ): void {
844
- this.state = state
845
- this.additionStateData = additionStateData
846
- }
847
-
848
- private updateProperties(nextProperties: P, updateKeys: string[]): void {
849
- const preProperties = toJS(this.properties)
850
- this.properties = nextProperties
851
- this.setAttributes()
852
-
853
- // 触发更新节点 node:properties-change 的事件
854
- this.graphModel.eventCenter.emit(EventType.NODE_PROPERTIES_CHANGE, {
855
- id: this.id,
856
- keys: updateKeys,
857
- preProperties,
858
- properties: nextProperties,
859
- })
860
- }
861
-
862
- @action setProperty(key: string, val: any): void {
863
- const preProperties = toJS(this.properties)
864
- const nextProperties = cloneDeep(preProperties)
865
- // https://lodash.com/docs/4.17.15#set
866
- // 使用 lodash 的 set 方法更新某个属性,可以支持 key 为 'a.b.c' 的情况
867
- set(nextProperties, key, formatData(val))
868
-
869
- this.updateProperties(nextProperties, [key])
870
- }
871
-
872
- @action setProperties(properties: Record<string, any>): void {
873
- const preProperties = toJS(this.properties)
874
- const nextProperties = {
875
- ...preProperties,
876
- ...formatData(properties),
877
- }
878
-
879
- const updateKeys: string[] = []
880
- mapKeys(properties, (val, key) => {
881
- // key 存在于上一个 properties 并且与传入的值不相等 或者 key 不存在于上一个 properties
882
- if (
883
- (has(preProperties, key) && preProperties[key] !== val) ||
884
- !has(preProperties, key)
885
- ) {
886
- updateKeys.push(key)
887
- }
888
- })
889
-
890
- this.updateProperties(nextProperties, updateKeys)
891
- }
892
-
893
- @action deleteProperty(key: string): void {
894
- delete this.properties[key]
895
- this.setAttributes()
896
- }
897
-
898
- @action setStyle(key: string, val: any): void {
899
- this.style = {
900
- ...this.style,
901
- [key]: formatData(val),
902
- }
903
- }
904
-
905
- @action setStyles(styles: Record<string, any>): void {
906
- this.style = {
907
- ...this.style,
908
- ...formatData(styles),
909
- }
910
- }
911
-
912
- @action updateStyles(styles: Record<string, any>): void {
913
- this.style = {
914
- ...formatData(styles),
915
- }
916
- }
917
-
918
- @action setZIndex(zIndex = 1): void {
919
- this.zIndex = zIndex
920
- }
921
-
922
- @action updateAttributes(attributes: any) {
923
- assign(this, attributes)
924
- }
925
- // 堆叠模式变化时,更新zIndex
926
- @action
927
- updateZIndexByOverlap(overlapMode: OverlapMode, defaultZIndex) {
928
- switch (overlapMode) {
929
- case OverlapMode.DEFAULT:
930
- this.zIndex = 1
931
- break
932
- case OverlapMode.EDGE_TOP:
933
- this.zIndex = 0
934
- break
935
- case OverlapMode.INCREASE:
936
- this.zIndex = defaultZIndex
937
- break
938
- default:
939
- break
940
- }
941
- }
942
- }
943
-
944
- export namespace BaseNodeModel {
945
- export type PointTuple = [number, number]
946
- export type AnchorsOffsetItem = PointTuple | Point
947
- }
948
-
949
- export default BaseNodeModel