@logicflow/core 1.2.27 → 2.0.0-beta.0

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 (804) hide show
  1. package/.turbo/turbo-build$colon$dev.log +10 -0
  2. package/.turbo/turbo-build.log +42 -0
  3. package/CHANGELOG.md +2114 -0
  4. package/LICENSE +206 -0
  5. package/__tests__/algorithm/egde.test.ts +118 -0
  6. package/__tests__/algorithm/index.test.ts +69 -0
  7. package/__tests__/algorithm/outline.test.ts +43 -0
  8. package/__tests__/bugs/1545-spec.test.ts +38 -0
  9. package/__tests__/event/event.test.ts +22 -0
  10. package/__tests__/history/history.test.ts +28 -0
  11. package/__tests__/logicflow.test.ts +567 -0
  12. package/__tests__/model/graphmodel.test.ts +67 -0
  13. package/__tests__/util/compatible.test.ts +48 -0
  14. package/__tests__/util/edge.test.ts +224 -0
  15. package/__tests__/util/geometry.test.ts +14 -0
  16. package/__tests__/util/graph.test.ts +16 -0
  17. package/__tests__/util/matrix.test.ts +41 -0
  18. package/__tests__/util/node.test.ts +68 -0
  19. package/__tests__/util/sampling.test.ts +16 -0
  20. package/__tests__/util/vector.test.ts +50 -0
  21. package/__tests__/util/zIndex.test.ts +10 -0
  22. package/dist/{style/index.css → index.css} +64 -52
  23. package/dist/index.js +26 -0
  24. package/dist/index.js.map +1 -0
  25. package/es/LogicFlow.d.ts +966 -0
  26. package/es/LogicFlow.js +1174 -0
  27. package/es/LogicFlow.js.map +1 -0
  28. package/es/algorithm/edge.d.ts +15 -0
  29. package/es/algorithm/edge.js +57 -0
  30. package/es/algorithm/edge.js.map +1 -0
  31. package/es/algorithm/index.js +71 -0
  32. package/es/algorithm/index.js.map +1 -0
  33. package/es/algorithm/outline.d.ts +7 -0
  34. package/es/algorithm/outline.js +61 -0
  35. package/es/algorithm/outline.js.map +1 -0
  36. package/{types/constant/constant.d.ts → es/constant/index.d.ts} +23 -22
  37. package/es/constant/index.js +117 -0
  38. package/es/constant/index.js.map +1 -0
  39. package/es/event/eventArgs.d.ts +428 -0
  40. package/es/event/eventArgs.js +2 -0
  41. package/es/event/eventArgs.js.map +1 -0
  42. package/es/event/eventEmitter.d.ts +48 -0
  43. package/es/event/eventEmitter.js +92 -0
  44. package/es/event/eventEmitter.js.map +1 -0
  45. package/es/history/index.d.ts +23 -0
  46. package/es/history/index.js +111 -0
  47. package/es/history/index.js.map +1 -0
  48. package/es/index.css +210 -0
  49. package/{types → es}/index.d.ts +4 -6
  50. package/es/index.js +16 -0
  51. package/es/index.js.map +1 -0
  52. package/es/index.less +1 -0
  53. package/{types → es}/keyboard/index.d.ts +7 -8
  54. package/es/keyboard/index.js +87 -0
  55. package/es/keyboard/index.js.map +1 -0
  56. package/es/keyboard/shortcut.js +116 -0
  57. package/es/keyboard/shortcut.js.map +1 -0
  58. package/es/model/BaseModel.d.ts +181 -0
  59. package/es/model/BaseModel.js +2 -0
  60. package/es/model/BaseModel.js.map +1 -0
  61. package/{types → es}/model/EditConfigModel.d.ts +13 -8
  62. package/es/model/EditConfigModel.js +192 -0
  63. package/es/model/EditConfigModel.js.map +1 -0
  64. package/{types → es}/model/GraphModel.d.ts +118 -178
  65. package/es/model/GraphModel.js +1473 -0
  66. package/es/model/GraphModel.js.map +1 -0
  67. package/es/model/SnaplineModel.d.ts +34 -0
  68. package/es/model/SnaplineModel.js +217 -0
  69. package/es/model/SnaplineModel.js.map +1 -0
  70. package/{types → es}/model/TransformModel.d.ts +21 -11
  71. package/es/model/TransformModel.js +240 -0
  72. package/es/model/TransformModel.js.map +1 -0
  73. package/{types → es}/model/edge/BaseEdgeModel.d.ts +82 -63
  74. package/es/model/edge/BaseEdgeModel.js +739 -0
  75. package/es/model/edge/BaseEdgeModel.js.map +1 -0
  76. package/es/model/edge/BezierEdgeModel.d.ts +63 -0
  77. package/es/model/edge/BezierEdgeModel.js +244 -0
  78. package/es/model/edge/BezierEdgeModel.js.map +1 -0
  79. package/es/model/edge/LineEdgeModel.d.ts +19 -0
  80. package/es/model/edge/LineEdgeModel.js +77 -0
  81. package/es/model/edge/LineEdgeModel.js.map +1 -0
  82. package/es/model/edge/PolylineEdgeModel.d.ts +85 -0
  83. package/es/model/edge/PolylineEdgeModel.js +593 -0
  84. package/es/model/edge/PolylineEdgeModel.js.map +1 -0
  85. package/es/model/edge/index.js +5 -0
  86. package/es/model/edge/index.js.map +1 -0
  87. package/es/model/index.js +8 -0
  88. package/es/model/index.js.map +1 -0
  89. package/es/model/node/BaseNodeModel.d.ts +260 -0
  90. package/es/model/node/BaseNodeModel.js +883 -0
  91. package/es/model/node/BaseNodeModel.js.map +1 -0
  92. package/es/model/node/CircleNodeModel.d.ts +40 -0
  93. package/es/model/node/CircleNodeModel.js +110 -0
  94. package/es/model/node/CircleNodeModel.js.map +1 -0
  95. package/es/model/node/DiamondNodeModel.d.ts +46 -0
  96. package/es/model/node/DiamondNodeModel.js +187 -0
  97. package/es/model/node/DiamondNodeModel.js.map +1 -0
  98. package/es/model/node/EllipseNodeModel.d.ts +42 -0
  99. package/es/model/node/EllipseNodeModel.js +118 -0
  100. package/es/model/node/EllipseNodeModel.js.map +1 -0
  101. package/es/model/node/HtmlNodeModel.d.ts +21 -0
  102. package/es/model/node/HtmlNodeModel.js +59 -0
  103. package/es/model/node/HtmlNodeModel.js.map +1 -0
  104. package/es/model/node/PolygonNodeModel.d.ts +50 -0
  105. package/es/model/node/PolygonNodeModel.js +196 -0
  106. package/es/model/node/PolygonNodeModel.js.map +1 -0
  107. package/es/model/node/RectNodeModel.d.ts +34 -0
  108. package/es/model/node/RectNodeModel.js +80 -0
  109. package/es/model/node/RectNodeModel.js.map +1 -0
  110. package/es/model/node/TextNodeModel.d.ts +27 -0
  111. package/es/model/node/TextNodeModel.js +113 -0
  112. package/es/model/node/TextNodeModel.js.map +1 -0
  113. package/es/model/node/index.js +9 -0
  114. package/es/model/node/index.js.map +1 -0
  115. package/es/options.d.ts +86 -0
  116. package/es/options.js +74 -0
  117. package/es/options.js.map +1 -0
  118. package/es/style/index.css +210 -0
  119. package/es/style/index.less +256 -0
  120. package/es/style/raw.d.ts +4 -0
  121. package/es/style/raw.js +6 -0
  122. package/es/style/raw.js.map +1 -0
  123. package/es/tool/MultipleSelectTool.d.ts +13 -0
  124. package/es/tool/MultipleSelectTool.js +159 -0
  125. package/es/tool/MultipleSelectTool.js.map +1 -0
  126. package/es/tool/TextEditTool.d.ts +26 -0
  127. package/es/tool/TextEditTool.js +187 -0
  128. package/es/tool/TextEditTool.js.map +1 -0
  129. package/es/tool/index.d.ts +2 -0
  130. package/es/tool/index.js +3 -0
  131. package/es/tool/index.js.map +1 -0
  132. package/{types/tool/SnaplineTool.d.ts → es/tool/snapline.d.ts} +1 -1
  133. package/es/tool/snapline.js +13 -0
  134. package/es/tool/snapline.js.map +1 -0
  135. package/es/tool/tool.d.ts +22 -0
  136. package/es/tool/tool.js +43 -0
  137. package/es/tool/tool.js.map +1 -0
  138. package/es/util/animation.d.ts +12 -0
  139. package/es/util/animation.js +20 -0
  140. package/es/util/animation.js.map +1 -0
  141. package/es/util/browser.js +3 -0
  142. package/es/util/browser.js.map +1 -0
  143. package/es/util/compatible.d.ts +6 -0
  144. package/es/util/compatible.js +17 -0
  145. package/es/util/compatible.js.map +1 -0
  146. package/es/util/drag.d.ts +47 -0
  147. package/es/util/drag.js +139 -0
  148. package/es/util/drag.js.map +1 -0
  149. package/es/util/edge.d.ts +94 -0
  150. package/es/util/edge.js +833 -0
  151. package/es/util/edge.js.map +1 -0
  152. package/es/util/geometry.d.ts +11 -0
  153. package/es/util/geometry.js +72 -0
  154. package/es/util/geometry.js.map +1 -0
  155. package/{types → es}/util/graph.d.ts +4 -3
  156. package/es/util/graph.js +54 -0
  157. package/es/util/graph.js.map +1 -0
  158. package/es/util/index.d.ts +16 -0
  159. package/es/util/index.js +17 -0
  160. package/es/util/index.js.map +1 -0
  161. package/{types → es}/util/matrix.d.ts +1 -1
  162. package/es/util/matrix.js +161 -0
  163. package/es/util/matrix.js.map +1 -0
  164. package/es/util/mobx.js +4 -0
  165. package/es/util/mobx.js.map +1 -0
  166. package/es/util/node.d.ts +69 -0
  167. package/es/util/node.js +402 -0
  168. package/es/util/node.js.map +1 -0
  169. package/es/util/raf.d.ts +2 -0
  170. package/es/util/raf.js +24 -0
  171. package/es/util/raf.js.map +1 -0
  172. package/{types → es}/util/sampling.d.ts +4 -2
  173. package/es/util/sampling.js +66 -0
  174. package/es/util/sampling.js.map +1 -0
  175. package/es/util/theme.d.ts +4 -0
  176. package/es/util/theme.js +156 -0
  177. package/es/util/theme.js.map +1 -0
  178. package/es/util/uuid.d.ts +7 -0
  179. package/es/util/uuid.js +20 -0
  180. package/es/util/uuid.js.map +1 -0
  181. package/{types → es}/util/vector.d.ts +2 -2
  182. package/es/util/vector.js +97 -0
  183. package/es/util/vector.js.map +1 -0
  184. package/es/util/zIndex.js +5 -0
  185. package/es/util/zIndex.js.map +1 -0
  186. package/es/view/Anchor.d.ts +47 -0
  187. package/es/view/Anchor.js +315 -0
  188. package/es/view/Anchor.js.map +1 -0
  189. package/es/view/Control.d.ts +100 -0
  190. package/es/view/Control.js +324 -0
  191. package/es/view/Control.js.map +1 -0
  192. package/es/view/Graph.d.ts +18 -0
  193. package/es/view/Graph.js +77 -0
  194. package/es/view/Graph.js.map +1 -0
  195. package/{types → es}/view/Rotate.d.ts +9 -9
  196. package/es/view/Rotate.js +108 -0
  197. package/es/view/Rotate.js.map +1 -0
  198. package/es/view/behavior/dnd.d.ts +27 -0
  199. package/es/view/behavior/dnd.js +110 -0
  200. package/es/view/behavior/dnd.js.map +1 -0
  201. package/es/view/edge/AdjustPoint.d.ts +50 -0
  202. package/es/view/edge/AdjustPoint.js +368 -0
  203. package/es/view/edge/AdjustPoint.js.map +1 -0
  204. package/es/view/edge/Arrow.d.ts +25 -0
  205. package/es/view/edge/Arrow.js +60 -0
  206. package/es/view/edge/Arrow.js.map +1 -0
  207. package/{types → es}/view/edge/BaseEdge.d.ts +25 -17
  208. package/es/view/edge/BaseEdge.js +381 -0
  209. package/es/view/edge/BaseEdge.js.map +1 -0
  210. package/es/view/edge/BezierEdge.d.ts +26 -0
  211. package/es/view/edge/BezierEdge.js +118 -0
  212. package/es/view/edge/BezierEdge.js.map +1 -0
  213. package/{types → es}/view/edge/LineEdge.d.ts +9 -4
  214. package/es/view/edge/LineEdge.js +78 -0
  215. package/es/view/edge/LineEdge.js.map +1 -0
  216. package/{types → es}/view/edge/PolylineEdge.d.ts +18 -8
  217. package/es/view/edge/PolylineEdge.js +274 -0
  218. package/es/view/edge/PolylineEdge.js.map +1 -0
  219. package/es/view/edge/index.d.ts +6 -0
  220. package/es/view/edge/index.js +7 -0
  221. package/es/view/edge/index.js.map +1 -0
  222. package/es/view/index.d.ts +7 -0
  223. package/es/view/index.js +8 -0
  224. package/es/view/index.js.map +1 -0
  225. package/es/view/node/BaseNode.d.ts +49 -0
  226. package/es/view/node/BaseNode.js +420 -0
  227. package/es/view/node/BaseNode.js.map +1 -0
  228. package/es/view/node/CircleNode.d.ts +10 -0
  229. package/es/view/node/CircleNode.js +45 -0
  230. package/es/view/node/CircleNode.js.map +1 -0
  231. package/es/view/node/DiamondNode.d.ts +10 -0
  232. package/es/view/node/DiamondNode.js +44 -0
  233. package/es/view/node/DiamondNode.js.map +1 -0
  234. package/es/view/node/EllipseNode.d.ts +10 -0
  235. package/es/view/node/EllipseNode.js +44 -0
  236. package/es/view/node/EllipseNode.js.map +1 -0
  237. package/{types → es}/view/node/HtmlNode.d.ts +15 -9
  238. package/es/view/node/HtmlNode.js +129 -0
  239. package/es/view/node/HtmlNode.js.map +1 -0
  240. package/es/view/node/PolygonNode.d.ts +10 -0
  241. package/es/view/node/PolygonNode.js +48 -0
  242. package/es/view/node/PolygonNode.js.map +1 -0
  243. package/es/view/node/RectNode.d.ts +11 -0
  244. package/es/view/node/RectNode.js +44 -0
  245. package/es/view/node/RectNode.js.map +1 -0
  246. package/es/view/node/TextNode.d.ts +12 -0
  247. package/es/view/node/TextNode.js +55 -0
  248. package/es/view/node/TextNode.js.map +1 -0
  249. package/es/view/node/index.d.ts +8 -0
  250. package/es/view/node/index.js +9 -0
  251. package/es/view/node/index.js.map +1 -0
  252. package/{types → es}/view/overlay/BackgroundOverlay.d.ts +7 -7
  253. package/es/view/overlay/BackgroundOverlay.js +31 -0
  254. package/es/view/overlay/BackgroundOverlay.js.map +1 -0
  255. package/es/view/overlay/BezierAdjustOverlay.d.ts +31 -0
  256. package/es/view/overlay/BezierAdjustOverlay.js +142 -0
  257. package/es/view/overlay/BezierAdjustOverlay.js.map +1 -0
  258. package/{types → es}/view/overlay/CanvasOverlay.d.ts +8 -11
  259. package/es/view/overlay/CanvasOverlay.js +172 -0
  260. package/es/view/overlay/CanvasOverlay.js.map +1 -0
  261. package/es/view/overlay/Grid.d.ts +30 -0
  262. package/es/view/overlay/Grid.js +118 -0
  263. package/es/view/overlay/Grid.js.map +1 -0
  264. package/es/view/overlay/ModificationOverlay.d.ts +9 -0
  265. package/es/view/overlay/ModificationOverlay.js +43 -0
  266. package/es/view/overlay/ModificationOverlay.js.map +1 -0
  267. package/es/view/overlay/OutlineOverlay.d.ts +14 -0
  268. package/es/view/overlay/OutlineOverlay.js +134 -0
  269. package/es/view/overlay/OutlineOverlay.js.map +1 -0
  270. package/es/view/overlay/SnaplineOverlay.d.ts +10 -0
  271. package/es/view/overlay/SnaplineOverlay.js +60 -0
  272. package/es/view/overlay/SnaplineOverlay.js.map +1 -0
  273. package/es/view/overlay/ToolOverlay.d.ts +19 -0
  274. package/es/view/overlay/ToolOverlay.js +76 -0
  275. package/es/view/overlay/ToolOverlay.js.map +1 -0
  276. package/{types → es}/view/overlay/getTransformHoc.d.ts +17 -14
  277. package/es/view/overlay/getTransformHoc.js +57 -0
  278. package/es/view/overlay/getTransformHoc.js.map +1 -0
  279. package/es/view/overlay/index.d.ts +8 -0
  280. package/es/view/overlay/index.js +9 -0
  281. package/es/view/overlay/index.js.map +1 -0
  282. package/es/view/shape/Circle.d.ts +2 -0
  283. package/es/view/shape/Circle.js +57 -0
  284. package/es/view/shape/Circle.js.map +1 -0
  285. package/es/view/shape/Ellipse.d.ts +2 -0
  286. package/es/view/shape/Ellipse.js +58 -0
  287. package/es/view/shape/Ellipse.js.map +1 -0
  288. package/es/view/shape/Line.d.ts +2 -0
  289. package/es/view/shape/Line.js +54 -0
  290. package/es/view/shape/Line.js.map +1 -0
  291. package/es/view/shape/Path.d.ts +6 -0
  292. package/es/view/shape/Path.js +43 -0
  293. package/es/view/shape/Path.js.map +1 -0
  294. package/es/view/shape/Polygon.d.ts +8 -0
  295. package/es/view/shape/Polygon.js +56 -0
  296. package/es/view/shape/Polygon.js.map +1 -0
  297. package/es/view/shape/Polyline.d.ts +2 -0
  298. package/es/view/shape/Polyline.js +49 -0
  299. package/es/view/shape/Polyline.js.map +1 -0
  300. package/es/view/shape/Rect.d.ts +15 -0
  301. package/es/view/shape/Rect.js +60 -0
  302. package/es/view/shape/Rect.js.map +1 -0
  303. package/es/view/shape/Text.d.ts +2 -0
  304. package/es/view/shape/Text.js +110 -0
  305. package/es/view/shape/Text.js.map +1 -0
  306. package/es/view/shape/index.d.ts +8 -0
  307. package/es/view/shape/index.js +9 -0
  308. package/es/view/shape/index.js.map +1 -0
  309. package/es/view/text/BaseText.d.ts +25 -0
  310. package/es/view/text/BaseText.js +114 -0
  311. package/es/view/text/BaseText.js.map +1 -0
  312. package/es/view/text/LineText.d.ts +9 -0
  313. package/es/view/text/LineText.js +149 -0
  314. package/es/view/text/LineText.js.map +1 -0
  315. package/es/view/text/index.d.ts +2 -0
  316. package/es/view/text/index.js +3 -0
  317. package/es/view/text/index.js.map +1 -0
  318. package/lib/LogicFlow.d.ts +966 -0
  319. package/lib/LogicFlow.js +1203 -0
  320. package/lib/LogicFlow.js.map +1 -0
  321. package/lib/algorithm/edge.d.ts +15 -0
  322. package/lib/algorithm/edge.js +62 -0
  323. package/lib/algorithm/edge.js.map +1 -0
  324. package/lib/algorithm/index.d.ts +6 -0
  325. package/lib/algorithm/index.js +75 -0
  326. package/lib/algorithm/index.js.map +1 -0
  327. package/lib/algorithm/outline.d.ts +7 -0
  328. package/lib/algorithm/outline.js +69 -0
  329. package/lib/algorithm/outline.js.map +1 -0
  330. package/lib/constant/index.d.ts +102 -0
  331. package/lib/constant/index.js +120 -0
  332. package/lib/constant/index.js.map +1 -0
  333. package/lib/event/eventArgs.d.ts +428 -0
  334. package/lib/event/eventArgs.js +3 -0
  335. package/lib/event/eventArgs.js.map +1 -0
  336. package/lib/event/eventEmitter.d.ts +48 -0
  337. package/lib/event/eventEmitter.js +95 -0
  338. package/lib/event/eventEmitter.js.map +1 -0
  339. package/lib/history/index.d.ts +23 -0
  340. package/lib/history/index.js +114 -0
  341. package/lib/history/index.js.map +1 -0
  342. package/lib/index.css +210 -0
  343. package/lib/index.d.ts +12 -0
  344. package/lib/index.js +58 -0
  345. package/lib/index.js.map +1 -0
  346. package/lib/index.less +1 -0
  347. package/lib/keyboard/index.d.ts +31 -0
  348. package/lib/keyboard/index.js +93 -0
  349. package/lib/keyboard/index.js.map +1 -0
  350. package/lib/keyboard/shortcut.d.ts +3 -0
  351. package/lib/keyboard/shortcut.js +120 -0
  352. package/lib/keyboard/shortcut.js.map +1 -0
  353. package/lib/model/BaseModel.d.ts +181 -0
  354. package/lib/model/BaseModel.js +3 -0
  355. package/lib/model/BaseModel.js.map +1 -0
  356. package/lib/model/EditConfigModel.d.ts +114 -0
  357. package/lib/model/EditConfigModel.js +195 -0
  358. package/lib/model/EditConfigModel.js.map +1 -0
  359. package/lib/model/GraphModel.d.ts +426 -0
  360. package/lib/model/GraphModel.js +1479 -0
  361. package/lib/model/GraphModel.js.map +1 -0
  362. package/lib/model/SnaplineModel.d.ts +34 -0
  363. package/lib/model/SnaplineModel.js +220 -0
  364. package/lib/model/SnaplineModel.js.map +1 -0
  365. package/lib/model/TransformModel.d.ts +101 -0
  366. package/lib/model/TransformModel.js +243 -0
  367. package/lib/model/TransformModel.js.map +1 -0
  368. package/lib/model/edge/BaseEdgeModel.d.ts +270 -0
  369. package/lib/model/edge/BaseEdgeModel.js +742 -0
  370. package/lib/model/edge/BaseEdgeModel.js.map +1 -0
  371. package/lib/model/edge/BezierEdgeModel.d.ts +63 -0
  372. package/lib/model/edge/BezierEdgeModel.js +250 -0
  373. package/lib/model/edge/BezierEdgeModel.js.map +1 -0
  374. package/lib/model/edge/LineEdgeModel.d.ts +19 -0
  375. package/lib/model/edge/LineEdgeModel.js +83 -0
  376. package/lib/model/edge/LineEdgeModel.js.map +1 -0
  377. package/lib/model/edge/PolylineEdgeModel.d.ts +85 -0
  378. package/lib/model/edge/PolylineEdgeModel.js +596 -0
  379. package/lib/model/edge/PolylineEdgeModel.js.map +1 -0
  380. package/lib/model/edge/index.d.ts +4 -0
  381. package/lib/model/edge/index.js +21 -0
  382. package/lib/model/edge/index.js.map +1 -0
  383. package/lib/model/index.d.ts +7 -0
  384. package/lib/model/index.js +24 -0
  385. package/lib/model/index.js.map +1 -0
  386. package/lib/model/node/BaseNodeModel.d.ts +260 -0
  387. package/lib/model/node/BaseNodeModel.js +886 -0
  388. package/lib/model/node/BaseNodeModel.js.map +1 -0
  389. package/lib/model/node/CircleNodeModel.d.ts +40 -0
  390. package/lib/model/node/CircleNodeModel.js +116 -0
  391. package/lib/model/node/CircleNodeModel.js.map +1 -0
  392. package/lib/model/node/DiamondNodeModel.d.ts +46 -0
  393. package/lib/model/node/DiamondNodeModel.js +193 -0
  394. package/lib/model/node/DiamondNodeModel.js.map +1 -0
  395. package/lib/model/node/EllipseNodeModel.d.ts +42 -0
  396. package/lib/model/node/EllipseNodeModel.js +124 -0
  397. package/lib/model/node/EllipseNodeModel.js.map +1 -0
  398. package/lib/model/node/HtmlNodeModel.d.ts +21 -0
  399. package/lib/model/node/HtmlNodeModel.js +65 -0
  400. package/lib/model/node/HtmlNodeModel.js.map +1 -0
  401. package/lib/model/node/PolygonNodeModel.d.ts +50 -0
  402. package/lib/model/node/PolygonNodeModel.js +202 -0
  403. package/lib/model/node/PolygonNodeModel.js.map +1 -0
  404. package/lib/model/node/RectNodeModel.d.ts +34 -0
  405. package/lib/model/node/RectNodeModel.js +86 -0
  406. package/lib/model/node/RectNodeModel.js.map +1 -0
  407. package/lib/model/node/TextNodeModel.d.ts +27 -0
  408. package/lib/model/node/TextNodeModel.js +119 -0
  409. package/lib/model/node/TextNodeModel.js.map +1 -0
  410. package/lib/model/node/index.d.ts +8 -0
  411. package/lib/model/node/index.js +25 -0
  412. package/lib/model/node/index.js.map +1 -0
  413. package/lib/options.d.ts +86 -0
  414. package/lib/options.js +77 -0
  415. package/lib/options.js.map +1 -0
  416. package/lib/style/index.css +210 -0
  417. package/lib/style/index.less +256 -0
  418. package/lib/style/raw.d.ts +4 -0
  419. package/lib/style/raw.js +9 -0
  420. package/lib/style/raw.js.map +1 -0
  421. package/lib/tool/MultipleSelectTool.d.ts +13 -0
  422. package/lib/tool/MultipleSelectTool.js +161 -0
  423. package/lib/tool/MultipleSelectTool.js.map +1 -0
  424. package/lib/tool/TextEditTool.d.ts +26 -0
  425. package/lib/tool/TextEditTool.js +190 -0
  426. package/lib/tool/TextEditTool.js.map +1 -0
  427. package/lib/tool/index.d.ts +2 -0
  428. package/lib/tool/index.js +19 -0
  429. package/lib/tool/index.js.map +1 -0
  430. package/lib/tool/snapline.d.ts +3 -0
  431. package/lib/tool/snapline.js +17 -0
  432. package/lib/tool/snapline.js.map +1 -0
  433. package/lib/tool/tool.d.ts +22 -0
  434. package/lib/tool/tool.js +49 -0
  435. package/lib/tool/tool.js.map +1 -0
  436. package/lib/util/animation.d.ts +12 -0
  437. package/lib/util/animation.js +24 -0
  438. package/lib/util/animation.js.map +1 -0
  439. package/lib/util/browser.d.ts +1 -0
  440. package/lib/util/browser.js +6 -0
  441. package/lib/util/browser.js.map +1 -0
  442. package/lib/util/compatible.d.ts +6 -0
  443. package/lib/util/compatible.js +21 -0
  444. package/lib/util/compatible.js.map +1 -0
  445. package/lib/util/drag.d.ts +47 -0
  446. package/lib/util/drag.js +142 -0
  447. package/lib/util/drag.js.map +1 -0
  448. package/lib/util/edge.d.ts +94 -0
  449. package/lib/util/edge.js +879 -0
  450. package/lib/util/edge.js.map +1 -0
  451. package/lib/util/geometry.d.ts +11 -0
  452. package/lib/util/geometry.js +78 -0
  453. package/lib/util/geometry.js.map +1 -0
  454. package/lib/util/graph.d.ts +13 -0
  455. package/lib/util/graph.js +59 -0
  456. package/lib/util/graph.js.map +1 -0
  457. package/lib/util/index.d.ts +16 -0
  458. package/lib/util/index.js +33 -0
  459. package/lib/util/index.js.map +1 -0
  460. package/lib/util/matrix.d.ts +32 -0
  461. package/lib/util/matrix.js +164 -0
  462. package/lib/util/matrix.js.map +1 -0
  463. package/lib/util/mobx.d.ts +2 -0
  464. package/lib/util/mobx.js +13 -0
  465. package/lib/util/mobx.js.map +1 -0
  466. package/lib/util/node.d.ts +69 -0
  467. package/lib/util/node.js +424 -0
  468. package/lib/util/node.js.map +1 -0
  469. package/lib/util/raf.d.ts +2 -0
  470. package/lib/util/raf.js +29 -0
  471. package/lib/util/raf.js.map +1 -0
  472. package/lib/util/sampling.d.ts +6 -0
  473. package/lib/util/sampling.js +72 -0
  474. package/lib/util/sampling.js.map +1 -0
  475. package/lib/util/theme.d.ts +4 -0
  476. package/lib/util/theme.js +160 -0
  477. package/lib/util/theme.js.map +1 -0
  478. package/lib/util/uuid.d.ts +7 -0
  479. package/lib/util/uuid.js +25 -0
  480. package/lib/util/uuid.js.map +1 -0
  481. package/lib/util/vector.d.ts +23 -0
  482. package/lib/util/vector.js +101 -0
  483. package/lib/util/vector.js.map +1 -0
  484. package/lib/util/zIndex.d.ts +2 -0
  485. package/lib/util/zIndex.js +10 -0
  486. package/lib/util/zIndex.js.map +1 -0
  487. package/lib/view/Anchor.d.ts +47 -0
  488. package/lib/view/Anchor.js +317 -0
  489. package/lib/view/Anchor.js.map +1 -0
  490. package/lib/view/Control.d.ts +100 -0
  491. package/lib/view/Control.js +327 -0
  492. package/lib/view/Control.js.map +1 -0
  493. package/lib/view/Graph.d.ts +18 -0
  494. package/lib/view/Graph.js +79 -0
  495. package/lib/view/Graph.js.map +1 -0
  496. package/lib/view/Rotate.d.ts +21 -0
  497. package/lib/view/Rotate.js +113 -0
  498. package/lib/view/Rotate.js.map +1 -0
  499. package/lib/view/behavior/dnd.d.ts +27 -0
  500. package/lib/view/behavior/dnd.js +113 -0
  501. package/lib/view/behavior/dnd.js.map +1 -0
  502. package/lib/view/edge/AdjustPoint.d.ts +50 -0
  503. package/lib/view/edge/AdjustPoint.js +371 -0
  504. package/lib/view/edge/AdjustPoint.js.map +1 -0
  505. package/lib/view/edge/Arrow.d.ts +25 -0
  506. package/lib/view/edge/Arrow.js +63 -0
  507. package/lib/view/edge/Arrow.js.map +1 -0
  508. package/lib/view/edge/BaseEdge.d.ts +148 -0
  509. package/lib/view/edge/BaseEdge.js +407 -0
  510. package/lib/view/edge/BaseEdge.js.map +1 -0
  511. package/lib/view/edge/BezierEdge.d.ts +26 -0
  512. package/lib/view/edge/BezierEdge.js +124 -0
  513. package/lib/view/edge/BezierEdge.js.map +1 -0
  514. package/{types/view/edge/BezierEdge.d.ts → lib/view/edge/LineEdge.d.ts} +9 -10
  515. package/lib/view/edge/LineEdge.js +84 -0
  516. package/lib/view/edge/LineEdge.js.map +1 -0
  517. package/lib/view/edge/PolylineEdge.d.ts +55 -0
  518. package/lib/view/edge/PolylineEdge.js +280 -0
  519. package/lib/view/edge/PolylineEdge.js.map +1 -0
  520. package/lib/view/edge/index.d.ts +6 -0
  521. package/lib/view/edge/index.js +23 -0
  522. package/lib/view/edge/index.js.map +1 -0
  523. package/lib/view/index.d.ts +7 -0
  524. package/lib/view/index.js +24 -0
  525. package/lib/view/index.js.map +1 -0
  526. package/lib/view/node/BaseNode.d.ts +49 -0
  527. package/lib/view/node/BaseNode.js +424 -0
  528. package/lib/view/node/BaseNode.js.map +1 -0
  529. package/lib/view/node/CircleNode.d.ts +10 -0
  530. package/lib/view/node/CircleNode.js +51 -0
  531. package/lib/view/node/CircleNode.js.map +1 -0
  532. package/lib/view/node/DiamondNode.d.ts +10 -0
  533. package/lib/view/node/DiamondNode.js +50 -0
  534. package/lib/view/node/DiamondNode.js.map +1 -0
  535. package/lib/view/node/EllipseNode.d.ts +10 -0
  536. package/lib/view/node/EllipseNode.js +50 -0
  537. package/lib/view/node/EllipseNode.js.map +1 -0
  538. package/lib/view/node/HtmlNode.d.ts +38 -0
  539. package/lib/view/node/HtmlNode.js +135 -0
  540. package/lib/view/node/HtmlNode.js.map +1 -0
  541. package/lib/view/node/PolygonNode.d.ts +10 -0
  542. package/lib/view/node/PolygonNode.js +54 -0
  543. package/lib/view/node/PolygonNode.js.map +1 -0
  544. package/lib/view/node/RectNode.d.ts +11 -0
  545. package/lib/view/node/RectNode.js +50 -0
  546. package/lib/view/node/RectNode.js.map +1 -0
  547. package/lib/view/node/TextNode.d.ts +12 -0
  548. package/lib/view/node/TextNode.js +61 -0
  549. package/lib/view/node/TextNode.js.map +1 -0
  550. package/lib/view/node/index.d.ts +8 -0
  551. package/lib/view/node/index.js +25 -0
  552. package/lib/view/node/index.js.map +1 -0
  553. package/lib/view/overlay/BackgroundOverlay.d.ts +28 -0
  554. package/lib/view/overlay/BackgroundOverlay.js +34 -0
  555. package/lib/view/overlay/BackgroundOverlay.js.map +1 -0
  556. package/lib/view/overlay/BezierAdjustOverlay.d.ts +31 -0
  557. package/lib/view/overlay/BezierAdjustOverlay.js +145 -0
  558. package/lib/view/overlay/BezierAdjustOverlay.js.map +1 -0
  559. package/lib/view/overlay/CanvasOverlay.d.ts +25 -0
  560. package/lib/view/overlay/CanvasOverlay.js +175 -0
  561. package/lib/view/overlay/CanvasOverlay.js.map +1 -0
  562. package/lib/view/overlay/Grid.d.ts +30 -0
  563. package/lib/view/overlay/Grid.js +121 -0
  564. package/lib/view/overlay/Grid.js.map +1 -0
  565. package/lib/view/overlay/ModificationOverlay.d.ts +9 -0
  566. package/lib/view/overlay/ModificationOverlay.js +46 -0
  567. package/lib/view/overlay/ModificationOverlay.js.map +1 -0
  568. package/lib/view/overlay/OutlineOverlay.d.ts +14 -0
  569. package/lib/view/overlay/OutlineOverlay.js +137 -0
  570. package/lib/view/overlay/OutlineOverlay.js.map +1 -0
  571. package/lib/view/overlay/SnaplineOverlay.d.ts +10 -0
  572. package/lib/view/overlay/SnaplineOverlay.js +66 -0
  573. package/lib/view/overlay/SnaplineOverlay.js.map +1 -0
  574. package/lib/view/overlay/ToolOverlay.d.ts +19 -0
  575. package/lib/view/overlay/ToolOverlay.js +79 -0
  576. package/lib/view/overlay/ToolOverlay.js.map +1 -0
  577. package/lib/view/overlay/getTransformHoc.d.ts +37 -0
  578. package/lib/view/overlay/getTransformHoc.js +61 -0
  579. package/lib/view/overlay/getTransformHoc.js.map +1 -0
  580. package/lib/view/overlay/index.d.ts +8 -0
  581. package/lib/view/overlay/index.js +25 -0
  582. package/lib/view/overlay/index.js.map +1 -0
  583. package/lib/view/shape/Circle.d.ts +2 -0
  584. package/lib/view/shape/Circle.js +61 -0
  585. package/lib/view/shape/Circle.js.map +1 -0
  586. package/lib/view/shape/Ellipse.d.ts +2 -0
  587. package/lib/view/shape/Ellipse.js +62 -0
  588. package/lib/view/shape/Ellipse.js.map +1 -0
  589. package/lib/view/shape/Line.d.ts +2 -0
  590. package/lib/view/shape/Line.js +58 -0
  591. package/lib/view/shape/Line.js.map +1 -0
  592. package/lib/view/shape/Path.d.ts +6 -0
  593. package/lib/view/shape/Path.js +47 -0
  594. package/lib/view/shape/Path.js.map +1 -0
  595. package/lib/view/shape/Polygon.d.ts +8 -0
  596. package/lib/view/shape/Polygon.js +60 -0
  597. package/lib/view/shape/Polygon.js.map +1 -0
  598. package/lib/view/shape/Polyline.d.ts +2 -0
  599. package/lib/view/shape/Polyline.js +53 -0
  600. package/lib/view/shape/Polyline.js.map +1 -0
  601. package/lib/view/shape/Rect.d.ts +15 -0
  602. package/lib/view/shape/Rect.js +64 -0
  603. package/lib/view/shape/Rect.js.map +1 -0
  604. package/lib/view/shape/Text.d.ts +2 -0
  605. package/lib/view/shape/Text.js +114 -0
  606. package/lib/view/shape/Text.js.map +1 -0
  607. package/lib/view/shape/index.d.ts +8 -0
  608. package/lib/view/shape/index.js +25 -0
  609. package/lib/view/shape/index.js.map +1 -0
  610. package/lib/view/text/BaseText.d.ts +25 -0
  611. package/lib/view/text/BaseText.js +117 -0
  612. package/lib/view/text/BaseText.js.map +1 -0
  613. package/lib/view/text/LineText.d.ts +9 -0
  614. package/lib/view/text/LineText.js +155 -0
  615. package/lib/view/text/LineText.js.map +1 -0
  616. package/lib/view/text/index.d.ts +2 -0
  617. package/lib/view/text/index.js +19 -0
  618. package/lib/view/text/index.js.map +1 -0
  619. package/package.json +41 -88
  620. package/rollup.config.js +15 -0
  621. package/src/LogicFlow.tsx +1831 -0
  622. package/src/algorithm/edge.ts +68 -0
  623. package/src/algorithm/index.ts +68 -0
  624. package/src/algorithm/outline.ts +77 -0
  625. package/src/constant/index.ts +127 -0
  626. package/src/event/event.md +66 -0
  627. package/src/event/eventArgs.ts +476 -0
  628. package/src/event/eventEmitter.ts +153 -0
  629. package/src/history/index.ts +112 -0
  630. package/src/index.less +1 -0
  631. package/src/index.ts +21 -0
  632. package/src/keyboard/index.ts +106 -0
  633. package/src/keyboard/shortcut.ts +123 -0
  634. package/src/model/BaseModel.ts +223 -0
  635. package/src/model/EditConfigModel.ts +215 -0
  636. package/src/model/GraphModel.ts +1516 -0
  637. package/src/model/SnaplineModel.ts +238 -0
  638. package/src/model/TransformModel.ts +258 -0
  639. package/src/model/edge/BaseEdgeModel.ts +688 -0
  640. package/src/model/edge/BezierEdgeModel.ts +196 -0
  641. package/src/model/edge/LineEdgeModel.ts +26 -0
  642. package/src/model/edge/PolylineEdgeModel.ts +656 -0
  643. package/src/model/edge/index.ts +4 -0
  644. package/src/model/index.ts +8 -0
  645. package/src/model/node/BaseNodeModel.ts +839 -0
  646. package/src/model/node/CircleNodeModel.ts +89 -0
  647. package/src/model/node/DiamondNodeModel.ts +128 -0
  648. package/src/model/node/EllipseNodeModel.ts +94 -0
  649. package/src/model/node/HtmlNodeModel.ts +49 -0
  650. package/src/model/node/PolygonNodeModel.ts +147 -0
  651. package/src/model/node/RectNodeModel.ts +57 -0
  652. package/src/model/node/TextNodeModel.ts +41 -0
  653. package/src/model/node/index.ts +8 -0
  654. package/src/options.ts +173 -0
  655. package/src/style/index.less +256 -0
  656. package/src/style/raw.ts +217 -0
  657. package/src/tool/MultipleSelectTool.tsx +132 -0
  658. package/src/tool/TextEditTool.tsx +193 -0
  659. package/src/tool/index.ts +2 -0
  660. package/src/tool/snapline.ts +17 -0
  661. package/src/tool/tool.ts +66 -0
  662. package/src/typings.d.ts +5 -0
  663. package/src/util/animation.ts +29 -0
  664. package/src/util/browser.ts +4 -0
  665. package/src/util/compatible.ts +15 -0
  666. package/src/util/drag.ts +186 -0
  667. package/src/util/edge.ts +1034 -0
  668. package/src/util/geometry.ts +53 -0
  669. package/src/util/graph.ts +46 -0
  670. package/src/util/index.ts +16 -0
  671. package/src/util/matrix.ts +129 -0
  672. package/src/util/mobx.ts +23 -0
  673. package/src/util/node.ts +519 -0
  674. package/src/util/raf.ts +28 -0
  675. package/src/util/sampling.ts +85 -0
  676. package/src/util/theme.ts +180 -0
  677. package/src/util/uuid.ts +26 -0
  678. package/src/util/vector.ts +93 -0
  679. package/src/util/zIndex.ts +6 -0
  680. package/src/view/Anchor.tsx +407 -0
  681. package/src/view/Control.tsx +446 -0
  682. package/src/view/Graph.tsx +104 -0
  683. package/src/view/Rotate.tsx +112 -0
  684. package/src/view/behavior/dnd.ts +116 -0
  685. package/src/view/edge/AdjustPoint.tsx +439 -0
  686. package/src/view/edge/Arrow.tsx +54 -0
  687. package/src/view/edge/BaseEdge.tsx +489 -0
  688. package/src/view/edge/BezierEdge.tsx +101 -0
  689. package/src/view/edge/LineEdge.tsx +81 -0
  690. package/src/view/edge/PolylineEdge.tsx +299 -0
  691. package/src/view/edge/index.ts +6 -0
  692. package/src/view/index.ts +8 -0
  693. package/src/view/node/BaseNode.tsx +494 -0
  694. package/src/view/node/CircleNode.tsx +19 -0
  695. package/src/view/node/DiamondNode.tsx +22 -0
  696. package/src/view/node/EllipseNode.tsx +20 -0
  697. package/src/view/node/HtmlNode.tsx +92 -0
  698. package/src/view/node/PolygonNode.tsx +26 -0
  699. package/src/view/node/RectNode.tsx +28 -0
  700. package/src/view/node/TextNode.tsx +37 -0
  701. package/src/view/node/index.ts +8 -0
  702. package/src/view/overlay/BackgroundOverlay.tsx +39 -0
  703. package/src/view/overlay/BezierAdjustOverlay.tsx +150 -0
  704. package/src/view/overlay/CanvasOverlay.tsx +180 -0
  705. package/src/view/overlay/Grid.tsx +135 -0
  706. package/src/view/overlay/ModificationOverlay.tsx +31 -0
  707. package/src/view/overlay/OutlineOverlay.tsx +170 -0
  708. package/src/view/overlay/SnaplineOverlay.tsx +44 -0
  709. package/src/view/overlay/ToolOverlay.tsx +65 -0
  710. package/src/view/overlay/getTransformHoc.tsx +50 -0
  711. package/src/view/overlay/index.ts +8 -0
  712. package/src/view/shape/Circle.tsx +27 -0
  713. package/src/view/shape/Ellipse.tsx +28 -0
  714. package/src/view/shape/Line.tsx +24 -0
  715. package/src/view/shape/Path.tsx +19 -0
  716. package/src/view/shape/Polygon.tsx +36 -0
  717. package/src/view/shape/Polyline.tsx +19 -0
  718. package/src/view/shape/Rect.tsx +44 -0
  719. package/src/view/shape/Text.tsx +138 -0
  720. package/src/view/shape/index.ts +8 -0
  721. package/src/view/text/BaseText.tsx +96 -0
  722. package/src/view/text/LineText.tsx +154 -0
  723. package/src/view/text/index.ts +2 -0
  724. package/tsconfig.json +18 -0
  725. package/dist/entry.js +0 -7
  726. package/dist/logic-flow.js +0 -23
  727. package/dist/logic-flow.min.js +0 -23
  728. package/types/LogicFlow.d.ts +0 -581
  729. package/types/algorithm/edge.d.ts +0 -6
  730. package/types/algorithm/outline.d.ts +0 -35
  731. package/types/constant/DefaultAnimation.d.ts +0 -12
  732. package/types/constant/DefaultTheme.d.ts +0 -270
  733. package/types/event/eventEmitter.d.ts +0 -36
  734. package/types/history/History.d.ts +0 -20
  735. package/types/model/BaseModel.d.ts +0 -99
  736. package/types/model/SnaplineModel.d.ts +0 -33
  737. package/types/model/edge/BezierEdgeModel.d.ts +0 -51
  738. package/types/model/edge/LineEdgeModel.d.ts +0 -14
  739. package/types/model/edge/PolylineEdgeModel.d.ts +0 -63
  740. package/types/model/node/BaseNodeModel.d.ts +0 -232
  741. package/types/model/node/CircleNodeModel.d.ts +0 -21
  742. package/types/model/node/DiamondNodeModel.d.ts +0 -25
  743. package/types/model/node/EllipseNodeModel.d.ts +0 -22
  744. package/types/model/node/HtmlNodeModel.d.ts +0 -12
  745. package/types/model/node/PolygonNodeModel.d.ts +0 -28
  746. package/types/model/node/RectNodeModel.d.ts +0 -19
  747. package/types/model/node/TextNodeModel.d.ts +0 -19
  748. package/types/options.d.ts +0 -240
  749. package/types/tool/MultipleSelectTool.d.ts +0 -20
  750. package/types/tool/TextEditTool.d.ts +0 -34
  751. package/types/tool/index.d.ts +0 -13
  752. package/types/type/index.d.ts +0 -429
  753. package/types/util/animation.d.ts +0 -2
  754. package/types/util/compatible.d.ts +0 -1
  755. package/types/util/drag.d.ts +0 -38
  756. package/types/util/edge.d.ts +0 -108
  757. package/types/util/geometry.d.ts +0 -2
  758. package/types/util/index.d.ts +0 -7
  759. package/types/util/node.d.ts +0 -66
  760. package/types/util/raf.d.ts +0 -2
  761. package/types/util/theme.d.ts +0 -2
  762. package/types/util/uuid.d.ts +0 -6
  763. package/types/view/Anchor.d.ts +0 -54
  764. package/types/view/Graph.d.ts +0 -21
  765. package/types/view/basic-shape/Circle.d.ts +0 -2
  766. package/types/view/basic-shape/Ellipse.d.ts +0 -2
  767. package/types/view/basic-shape/Line.d.ts +0 -3
  768. package/types/view/basic-shape/LinearGradient.d.ts +0 -1
  769. package/types/view/basic-shape/Path.d.ts +0 -7
  770. package/types/view/basic-shape/Polygon.d.ts +0 -2
  771. package/types/view/basic-shape/Polyline.d.ts +0 -3
  772. package/types/view/basic-shape/Rect.d.ts +0 -14
  773. package/types/view/basic-shape/Text.d.ts +0 -2
  774. package/types/view/behavior/DnD.d.ts +0 -35
  775. package/types/view/behavior/Transform.d.ts +0 -4
  776. package/types/view/edge/AdjustPoint.d.ts +0 -56
  777. package/types/view/edge/Arrow.d.ts +0 -24
  778. package/types/view/edge/index.d.ts +0 -6
  779. package/types/view/index.d.ts +0 -2
  780. package/types/view/node/BaseNode.d.ts +0 -57
  781. package/types/view/node/CircleNode.d.ts +0 -5
  782. package/types/view/node/DiamondNode.d.ts +0 -5
  783. package/types/view/node/EllipseNode.d.ts +0 -5
  784. package/types/view/node/PolygonNode.d.ts +0 -5
  785. package/types/view/node/RectNode.d.ts +0 -5
  786. package/types/view/node/TextNode.d.ts +0 -6
  787. package/types/view/node/index.d.ts +0 -9
  788. package/types/view/overlay/BezierAdjustOverlay.d.ts +0 -12
  789. package/types/view/overlay/Grid.d.ts +0 -30
  790. package/types/view/overlay/HtmlOverlay.d.ts +0 -15
  791. package/types/view/overlay/ModificationOverlay.d.ts +0 -9
  792. package/types/view/overlay/OutlineOverlay.d.ts +0 -17
  793. package/types/view/overlay/SnaplineOverlay.d.ts +0 -9
  794. package/types/view/overlay/ToolOverlay.d.ts +0 -17
  795. package/types/view/text/BaseText.d.ts +0 -29
  796. package/types/view/text/LineText.d.ts +0 -9
  797. /package/{types → es}/algorithm/index.d.ts +0 -0
  798. /package/{types → es}/keyboard/shortcut.d.ts +0 -0
  799. /package/{types → es}/model/edge/index.d.ts +0 -0
  800. /package/{types → es}/model/index.d.ts +0 -0
  801. /package/{types → es}/model/node/index.d.ts +0 -0
  802. /package/{types → es}/util/browser.d.ts +0 -0
  803. /package/{types → es}/util/mobx.d.ts +0 -0
  804. /package/{types → es}/util/zIndex.d.ts +0 -0
@@ -0,0 +1,1516 @@
1
+ import { find, forEach, map } from 'lodash-es'
2
+ import { action, computed, observable } from 'mobx'
3
+ import {
4
+ BaseEdgeModel,
5
+ BaseNodeModel,
6
+ EditConfigModel,
7
+ Model,
8
+ PolylineEdgeModel,
9
+ TransformModel,
10
+ } from '.'
11
+ import {
12
+ DEFAULT_VISIBLE_SPACE,
13
+ ELEMENT_MAX_Z_INDEX,
14
+ ElementState,
15
+ ElementType,
16
+ EventType,
17
+ ModelType,
18
+ OverlapMode,
19
+ } from '../constant'
20
+ import LogicFlow from '../LogicFlow'
21
+ import { Options as LFOptions } from '../options'
22
+ import {
23
+ createEdgeGenerator,
24
+ createUuid,
25
+ formatData,
26
+ getClosestPointOfPolyline,
27
+ getMinIndex,
28
+ getNodeAnchorPosition,
29
+ getNodeBBox,
30
+ getZIndex,
31
+ isPointInArea,
32
+ setupAnimation,
33
+ setupTheme,
34
+ snapToGrid,
35
+ updateTheme,
36
+ } from '../util'
37
+ import EventEmitter from '../event/eventEmitter'
38
+
39
+ import Position = LogicFlow.Position
40
+ import PointTuple = LogicFlow.PointTuple
41
+ import GraphData = LogicFlow.GraphData
42
+ import NodeConfig = LogicFlow.NodeConfig
43
+ import BaseNodeModelCtor = LogicFlow.BaseNodeModelCtor
44
+ import BaseEdgeModelCtor = LogicFlow.BaseEdgeModelCtor
45
+
46
+ export interface Constructable<T> {
47
+ new (...args: any): T
48
+ }
49
+
50
+ export class GraphModel {
51
+ /**
52
+ * LogicFlow画布挂载元素
53
+ * 也就是初始化LogicFlow实例时传入的container
54
+ */
55
+ public readonly rootEl: HTMLElement
56
+ readonly flowId?: string // 流程图 ID
57
+ @observable width: number // 画布宽度
58
+ @observable height: number // 画布高度
59
+
60
+ // 流程图主题配置
61
+ theme: LogicFlow.Theme
62
+ // 事件中心
63
+ readonly eventCenter: EventEmitter
64
+ // 维护所有节点和边类型对应的 model
65
+ readonly modelMap: Map<string, LogicFlow.GraphElementCtor> = new Map()
66
+ /**
67
+ * 位于当前画布顶部的元素
68
+ * 此元素只在堆叠模式为默认模式下存在
69
+ * 用于在默认模式下将之前的顶部元素回复初始高度
70
+ */
71
+ topElement?: BaseNodeModel | BaseEdgeModel
72
+ // 控制是否开启动画
73
+ animation?: boolean | LFOptions.AnimationConfig
74
+ // 自定义全局 id 生成器
75
+ idGenerator?: (type?: string) => string | undefined
76
+ // 节点间连线、连线变更时的边的生成规则
77
+ edgeGenerator: LFOptions.Definition['edgeGenerator']
78
+
79
+ /**
80
+ * 节点移动规则判断
81
+ * 在节点移动的时候,会出发此数组中的所有规则判断
82
+ */
83
+
84
+ nodeMoveRules: Model.NodeMoveRule[] = []
85
+ /**
86
+ * 获取自定义连线轨迹
87
+ */
88
+ customTrajectory: LFOptions.Definition['customTrajectory']
89
+
90
+ // 在图上操作创建边时,默认使用的边类型.
91
+ @observable edgeType: string
92
+ // 当前图上所有节点的model
93
+ @observable nodes: BaseNodeModel[] = []
94
+ // 当前图上所有边的model
95
+ @observable edges: BaseEdgeModel[] = []
96
+ // 外部拖动节点进入画布的过程中,用fakeNode来和画布上正是的节点区分开
97
+ @observable fakeNode?: BaseNodeModel | null
98
+
99
+ /**
100
+ * 元素重合时堆叠模式:
101
+ * - DEFAULT(默认模式):节点和边被选中,会被显示在最上面。当取消选中后,元素会恢复之前的层级
102
+ * - INCREASE(递增模式):节点和边被选中,会被显示在最上面。当取消选中后,元素会保持当前层级
103
+ */
104
+ @observable overlapMode = OverlapMode.DEFAULT
105
+ // 背景配置
106
+ @observable background?: boolean | LFOptions.BackgroundConfig
107
+ // 网格大小
108
+ @observable gridSize: number = 1
109
+ // 控制画布的缩放、平移
110
+ @observable transformModel: TransformModel
111
+ // 控制流程图编辑相关配置项 Model
112
+ @observable editConfigModel: EditConfigModel
113
+ // 控制是否开启局部渲染
114
+ @observable partial: boolean = false;
115
+
116
+ // 用户自定义属性
117
+ [propName: string]: any
118
+
119
+ constructor(options: LFOptions.Common) {
120
+ const {
121
+ container,
122
+ partial,
123
+ background = {},
124
+ grid,
125
+ idGenerator,
126
+ edgeGenerator,
127
+ animation,
128
+ customTrajectory,
129
+ } = options
130
+ this.rootEl = container
131
+ this.partial = !!partial
132
+ this.background = background
133
+ if (typeof grid === 'object') {
134
+ this.gridSize = grid.size || 1 // 默认 gridSize 设置为 1
135
+ }
136
+ this.theme = setupTheme(options.style)
137
+ this.edgeType = options.edgeType || 'polyline'
138
+ this.animation = setupAnimation(animation)
139
+ this.overlapMode = options.overlapMode || OverlapMode.DEFAULT
140
+
141
+ this.width = options.width || this.rootEl.getBoundingClientRect().width
142
+ this.height = options.height || this.rootEl.getBoundingClientRect().height
143
+
144
+ this.eventCenter = new EventEmitter()
145
+ this.editConfigModel = new EditConfigModel(options)
146
+ this.transformModel = new TransformModel(this.eventCenter, options)
147
+
148
+ this.flowId = createUuid()
149
+ this.idGenerator = idGenerator
150
+ this.edgeGenerator = createEdgeGenerator(this, edgeGenerator)
151
+ this.customTrajectory = customTrajectory
152
+ }
153
+
154
+ @computed get nodesMap(): GraphModel.NodesMapType {
155
+ return this.nodes.reduce((nMap, model, index) => {
156
+ nMap[model.id] = {
157
+ index,
158
+ model,
159
+ }
160
+ return nMap
161
+ }, {} as GraphModel.NodesMapType)
162
+ }
163
+
164
+ @computed get edgesMap(): {
165
+ [key: string]: { index: number; model: BaseEdgeModel }
166
+ } {
167
+ return this.edges.reduce((eMap, model, index) => {
168
+ eMap[model.id] = {
169
+ index,
170
+ model,
171
+ }
172
+ return eMap
173
+ }, {})
174
+ }
175
+
176
+ @computed get modelsMap(): GraphModel.ModelsMapType {
177
+ return [...this.nodes, ...this.edges].reduce((eMap, model) => {
178
+ eMap[model.id] = model
179
+ return eMap
180
+ }, {})
181
+ }
182
+
183
+ /**
184
+ * 基于zIndex对元素进行排序。
185
+ * todo: 性能优化
186
+ */
187
+ @computed get sortElements() {
188
+ const elements = [...this.nodes, ...this.edges].sort(
189
+ (a, b) => a.zIndex - b.zIndex,
190
+ )
191
+
192
+ // 只显示可见区域的节点和边
193
+ const visibleElements: (BaseNodeModel | BaseEdgeModel)[] = []
194
+ // TODO: 缓存,优化计算效率 by xutao. So what to do?
195
+ const visibleLt: PointTuple = [
196
+ -DEFAULT_VISIBLE_SPACE,
197
+ -DEFAULT_VISIBLE_SPACE,
198
+ ]
199
+ const visibleRb: PointTuple = [
200
+ this.width + DEFAULT_VISIBLE_SPACE,
201
+ this.height + DEFAULT_VISIBLE_SPACE,
202
+ ]
203
+ for (let i = 0; i < elements.length; i++) {
204
+ const currentItem = elements[i]
205
+ // 如果节点不在可见区域,且不是全元素显示模式,则隐藏节点。
206
+ if (
207
+ currentItem.visible &&
208
+ (!this.partial ||
209
+ currentItem.isSelected ||
210
+ this.isElementInArea(currentItem, visibleLt, visibleRb, false, false))
211
+ ) {
212
+ visibleElements.push(currentItem)
213
+ }
214
+ }
215
+ return visibleElements
216
+ }
217
+
218
+ /**
219
+ * 当前编辑的元素,低频操作,先循环找。
220
+ */
221
+ @computed get textEditElement() {
222
+ const textEditNode = this.nodes.find(
223
+ (node) => node.state === ElementState.TEXT_EDIT,
224
+ )
225
+ const textEditEdge = this.edges.find(
226
+ (edge) => edge.state === ElementState.TEXT_EDIT,
227
+ )
228
+ return textEditNode || textEditEdge
229
+ }
230
+
231
+ /**
232
+ * 当前画布所有被选中的元素
233
+ */
234
+ @computed get selectElements() {
235
+ const elements = new Map<string, BaseNodeModel | BaseEdgeModel>()
236
+ this.nodes.forEach((node) => {
237
+ if (node.isSelected) {
238
+ elements.set(node.id, node)
239
+ }
240
+ })
241
+ this.edges.forEach((edge) => {
242
+ if (edge.isSelected) {
243
+ elements.set(edge.id, edge)
244
+ }
245
+ })
246
+ return elements
247
+ }
248
+
249
+ @computed get selectNodes() {
250
+ const nodes: BaseNodeModel[] = []
251
+ this.nodes.forEach((node) => {
252
+ if (node.isSelected) {
253
+ nodes.push(node)
254
+ }
255
+ })
256
+ return nodes
257
+ }
258
+
259
+ /**
260
+ * 获取指定区域内的所有元素
261
+ * @param leftTopPoint 表示区域左上角的点
262
+ * @param rightBottomPoint 表示区域右下角的点
263
+ * @param wholeEdge 是否要整个边都在区域内部
264
+ * @param wholeNode 是否要整个节点都在区域内部
265
+ * @param ignoreHideElement 是否忽略隐藏的节点
266
+ */
267
+ // TODO: rename getAreaElement to getElementsInArea or getAreaElements
268
+ getAreaElement(
269
+ leftTopPoint: PointTuple,
270
+ rightBottomPoint: PointTuple,
271
+ wholeEdge = true,
272
+ wholeNode = true,
273
+ ignoreHideElement = false,
274
+ ) {
275
+ const areaElements: LogicFlow.GraphElement[] = []
276
+ forEach([...this.nodes, ...this.edges], (element) => {
277
+ const isElementInArea = this.isElementInArea(
278
+ element,
279
+ leftTopPoint,
280
+ rightBottomPoint,
281
+ wholeEdge,
282
+ wholeNode,
283
+ )
284
+ if ((!ignoreHideElement || element.visible) && isElementInArea) {
285
+ areaElements.push(element)
286
+ }
287
+ })
288
+ return areaElements
289
+ }
290
+
291
+ /**
292
+ * 获取指定类型元素对应的Model
293
+ */
294
+ getModel(type: string) {
295
+ return this.modelMap.get(type)
296
+ }
297
+
298
+ /**
299
+ * 基于Id获取节点的model
300
+ */
301
+ getNodeModelById(nodeId: string): BaseNodeModel | undefined {
302
+ if (this.fakeNode && nodeId === this.fakeNode.id) {
303
+ return this.fakeNode
304
+ }
305
+ return this.nodesMap[nodeId]?.model
306
+ }
307
+
308
+ /**
309
+ * 因为流程图所在的位置可以是页面任何地方
310
+ * 当内部事件需要获取触发事件时,其相对于画布左上角的位置
311
+ * 需要事件触发位置减去画布相对于client的位置
312
+ */
313
+ getPointByClient({
314
+ x: x1,
315
+ y: y1,
316
+ }: LogicFlow.Point): LogicFlow.ClientPosition {
317
+ const bbox = this.rootEl.getBoundingClientRect()
318
+ const domOverlayPosition: Position = {
319
+ x: x1 - bbox.left,
320
+ y: y1 - bbox.top,
321
+ }
322
+ const [x, y] = this.transformModel.HtmlPointToCanvasPoint([
323
+ domOverlayPosition.x,
324
+ domOverlayPosition.y,
325
+ ])
326
+ const canvasOverlayPosition: Position = { x, y }
327
+ return {
328
+ domOverlayPosition,
329
+ canvasOverlayPosition,
330
+ }
331
+ }
332
+
333
+ /**
334
+ * 判断一个元素是否在指定矩形区域内。
335
+ * @param element 节点或者边
336
+ * @param lt 左上角点
337
+ * @param rb 右下角点
338
+ * @param wholeEdge 边的起点和终点都在区域内才算
339
+ * @param wholeNode 节点的box都在区域内才算
340
+ */
341
+ isElementInArea(
342
+ element: BaseEdgeModel | BaseNodeModel,
343
+ lt: PointTuple,
344
+ rb: PointTuple,
345
+ wholeEdge = true,
346
+ wholeNode = true,
347
+ ) {
348
+ if (element.BaseType === ElementType.NODE) {
349
+ element = element as BaseNodeModel
350
+ // 节点是否在选区内,判断逻辑为如果节点的bbox的四个角上的点都在选区内,则判断节点在选区内
351
+ const { minX, minY, maxX, maxY } = getNodeBBox(element)
352
+ const bboxPointsList: Position[] = [
353
+ {
354
+ x: minX,
355
+ y: minY,
356
+ },
357
+ {
358
+ x: maxX,
359
+ y: minY,
360
+ },
361
+ {
362
+ x: maxX,
363
+ y: maxY,
364
+ },
365
+ {
366
+ x: minX,
367
+ y: maxY,
368
+ },
369
+ ]
370
+ let inArea = wholeNode
371
+ for (let i = 0; i < bboxPointsList.length; i++) {
372
+ let { x, y } = bboxPointsList[i]
373
+ ;[x, y] = this.transformModel.CanvasPointToHtmlPoint([x, y])
374
+ if (isPointInArea([x, y], lt, rb) !== wholeNode) {
375
+ inArea = !wholeNode
376
+ break
377
+ }
378
+ }
379
+ return inArea
380
+ }
381
+ if (element.BaseType === ElementType.EDGE) {
382
+ element = element as BaseEdgeModel
383
+ const { startPoint, endPoint } = element
384
+ const startHtmlPoint = this.transformModel.CanvasPointToHtmlPoint([
385
+ startPoint.x,
386
+ startPoint.y,
387
+ ])
388
+ const endHtmlPoint = this.transformModel.CanvasPointToHtmlPoint([
389
+ endPoint.x,
390
+ endPoint.y,
391
+ ])
392
+ const isStartInArea = isPointInArea(startHtmlPoint, lt, rb)
393
+ const isEndInArea = isPointInArea(endHtmlPoint, lt, rb)
394
+ return wholeEdge
395
+ ? isStartInArea && isEndInArea
396
+ : isStartInArea || isEndInArea
397
+ }
398
+ return false
399
+ }
400
+
401
+ /**
402
+ * 使用新的数据重新设置整个画布的元素
403
+ * 注意:将会清除画布上所有已有的节点和边
404
+ * @param { object } graphData 图数据
405
+ */
406
+ graphDataToModel(graphData: Partial<LogicFlow.GraphConfigData>) {
407
+ if (!this.width || !this.height) {
408
+ this.resize()
409
+ }
410
+ if (!graphData) {
411
+ this.nodes = []
412
+ this.edges = []
413
+ return
414
+ }
415
+ if (graphData.nodes) {
416
+ this.nodes = map(graphData.nodes, (node: NodeConfig) =>
417
+ this.getModelAfterSnapToGrid(node),
418
+ )
419
+ } else {
420
+ this.nodes = []
421
+ }
422
+ if (graphData.edges) {
423
+ this.edges = map(graphData.edges, (edge) => {
424
+ const Model = this.getModel(edge.type ?? '') as BaseEdgeModelCtor
425
+ if (!Model) {
426
+ throw new Error(`找不到${edge.type}对应的边。`)
427
+ }
428
+ return new Model(edge, this)
429
+ })
430
+ } else {
431
+ this.edges = []
432
+ }
433
+ }
434
+
435
+ /**
436
+ * 获取画布数据
437
+ */
438
+ modelToGraphData(): GraphData {
439
+ const edges: LogicFlow.EdgeData[] = []
440
+ this.edges.forEach((edge) => {
441
+ const data = edge.getData()
442
+ if (data && !edge.virtual) edges.push(data)
443
+ })
444
+ const nodes: LogicFlow.NodeData[] = []
445
+ this.nodes.forEach((node) => {
446
+ const data = node.getData()
447
+ if (data && !node.virtual) nodes.push(data)
448
+ })
449
+ return {
450
+ nodes,
451
+ edges,
452
+ }
453
+ }
454
+
455
+ // 用户history记录的数据,忽略拖拽过程中的数据变更
456
+ modelToHistoryData(): GraphData | false {
457
+ let nodeDragging = false
458
+ const nodes: LogicFlow.NodeData[] = []
459
+ // 如果有节点在拖拽中,不更新history
460
+ for (let i = 0; i < this.nodes.length; i++) {
461
+ const nodeModel = this.nodes[i]
462
+ if (nodeModel.isDragging) {
463
+ nodeDragging = true
464
+ break
465
+ } else {
466
+ nodes.push(nodeModel.getHistoryData())
467
+ }
468
+ }
469
+ if (nodeDragging) {
470
+ return false
471
+ }
472
+ // 如果有边在拖拽中,不更新history
473
+ let edgeDragging = false
474
+ const edges: LogicFlow.EdgeData[] = []
475
+ for (let j = 0; j < this.edges.length; j++) {
476
+ const edgeMode = this.edges[j]
477
+ if (edgeMode.isDragging) {
478
+ edgeDragging = true
479
+ break
480
+ } else {
481
+ edges.push(edgeMode.getHistoryData())
482
+ }
483
+ }
484
+ if (edgeDragging) {
485
+ return false
486
+ }
487
+ return {
488
+ nodes,
489
+ edges,
490
+ }
491
+ }
492
+
493
+ /**
494
+ * 获取边的model
495
+ */
496
+ getEdgeModelById(edgeId: string): BaseEdgeModel | undefined {
497
+ return this.edgesMap[edgeId]?.model
498
+ }
499
+
500
+ /**
501
+ * 获取节点或者边的model
502
+ */
503
+ getElement(id: string): BaseNodeModel | BaseEdgeModel | undefined {
504
+ return this.modelsMap[id]
505
+ }
506
+
507
+ /**
508
+ * 所有节点上所有边的model
509
+ */
510
+ getNodeEdges(nodeId: string): BaseEdgeModel[] {
511
+ const edges: BaseEdgeModel[] = []
512
+ for (let i = 0; i < this.edges.length; i++) {
513
+ const edgeModel = this.edges[i]
514
+ const nodeAsSource = edgeModel.sourceNodeId === nodeId
515
+ const nodeAsTarget = edgeModel.targetNodeId === nodeId
516
+ if (nodeAsSource || nodeAsTarget) {
517
+ edges.push(edgeModel)
518
+ }
519
+ }
520
+ return edges
521
+ }
522
+
523
+ /**
524
+ * 获取选中的元素数据
525
+ * @param isIgnoreCheck 是否包括sourceNode和targetNode没有被选中的边,默认包括。
526
+ * 复制的时候不能包括此类边, 因为复制的时候不允许悬空的边
527
+ */
528
+ getSelectElements(isIgnoreCheck = true): GraphData {
529
+ const elements = this.selectElements
530
+ const graphData: GraphData = {
531
+ nodes: [],
532
+ edges: [],
533
+ }
534
+ elements.forEach((element) => {
535
+ if (element.BaseType === ElementType.NODE) {
536
+ graphData.nodes.push(element.getData())
537
+ }
538
+ if (element.BaseType === ElementType.EDGE) {
539
+ const edgeData = element.getData()
540
+ const isNodeSelected =
541
+ elements.get(edgeData.sourceNodeId) &&
542
+ elements.get(edgeData.targetNodeId)
543
+
544
+ if (isIgnoreCheck || isNodeSelected) {
545
+ graphData.edges.push(edgeData)
546
+ }
547
+ }
548
+ })
549
+ return graphData
550
+ }
551
+
552
+ /**
553
+ * 修改对应元素 model 中的属性
554
+ * 注意:此方法慎用,除非您对logicflow内部有足够的了解。
555
+ * 大多数情况下,请使用setProperties、updateText、changeNodeId等方法。
556
+ * 例如直接使用此方法修改节点的id,那么就是会导致连接到此节点的边的sourceNodeId出现找不到的情况。
557
+ * @param {string} id 元素id
558
+ * @param {object} attributes 需要更新的属性
559
+ */
560
+ updateAttributes(id: string, attributes: object) {
561
+ const element = this.getElement(id)
562
+ element?.updateAttributes(attributes)
563
+ }
564
+
565
+ /**
566
+ * 修改节点的id, 如果不传新的id,会内部自动创建一个。
567
+ * @param { string } nodeId 将要被修改的id
568
+ * @param { string } newId 可选,修改后的id
569
+ * @returns 修改后的节点id, 如果传入的oldId不存在,返回空字符串
570
+ */
571
+ changeNodeId(nodeId: string, newId?: string): string {
572
+ if (!newId) {
573
+ newId = createUuid()
574
+ }
575
+ if (this.nodesMap[newId]) {
576
+ console.warn(`当前流程图已存在节点${newId}, 修改失败`)
577
+ return ''
578
+ }
579
+ if (!this.nodesMap[nodeId]) {
580
+ console.warn(`当前流程图找不到节点${nodeId}, 修改失败`)
581
+ return ''
582
+ }
583
+ this.edges.forEach((edge) => {
584
+ if (edge.sourceNodeId === nodeId) {
585
+ edge.sourceNodeId = newId as string
586
+ }
587
+ if (edge.targetNodeId === nodeId) {
588
+ edge.targetNodeId = newId as string
589
+ }
590
+ })
591
+ this.nodesMap[nodeId].model.id = newId
592
+ this.nodesMap[newId] = this.nodesMap[nodeId]
593
+ return newId
594
+ }
595
+
596
+ /**
597
+ * 修改边的id, 如果不传新的id,会内部自动创建一个。
598
+ * @param { string } oldId 将要被修改的id
599
+ * @param { string } newId 可选,修改后的id
600
+ * @returns 修改后的节点id, 如果传入的oldId不存在,返回空字符串
601
+ */
602
+ changeEdgeId<T extends string>(oldId: string, newId?: string): T | string {
603
+ if (!newId) {
604
+ newId = createUuid()
605
+ }
606
+ if (this.edgesMap[newId]) {
607
+ console.warn(`当前流程图已存在边: ${newId}, 修改失败`)
608
+ return ''
609
+ }
610
+ if (!this.edgesMap[oldId]) {
611
+ console.warn(`当前流程图找不到边: ${newId}, 修改失败`)
612
+ return ''
613
+ }
614
+ this.edges.forEach((edge) => {
615
+ if (edge.id === oldId) {
616
+ // edge.id = newId
617
+ edge.changeEdgeId(newId as string)
618
+ }
619
+ })
620
+ return newId
621
+ }
622
+
623
+ /**
624
+ * 内部保留方法,请勿直接使用
625
+ */
626
+ @action
627
+ setFakeNode(nodeModel: BaseNodeModel) {
628
+ this.fakeNode = nodeModel
629
+ }
630
+
631
+ /**
632
+ * 内部保留方法,请勿直接使用
633
+ */
634
+ @action
635
+ removeFakeNode() {
636
+ this.fakeNode = null
637
+ }
638
+
639
+ /**
640
+ * 设置指定类型的Model,请勿直接使用
641
+ */
642
+ @action
643
+ setModel(type: string, ModelClass: LogicFlow.GraphElementCtor) {
644
+ return this.modelMap.set(type, ModelClass)
645
+ }
646
+
647
+ /**
648
+ * 将某个元素放置到顶部。
649
+ * 如果堆叠模式为默认模式,则将原置顶元素重新恢复原有层级。
650
+ * 如果堆叠模式为递增模式,则将需指定元素zIndex设置为当前最大zIndex + 1。
651
+ * @see todo link 堆叠模式
652
+ * @param id 元素Id
653
+ */
654
+ @action
655
+ toFront(id: string) {
656
+ const element = this.nodesMap[id]?.model || this.edgesMap[id]?.model
657
+ if (element) {
658
+ if (this.overlapMode === OverlapMode.DEFAULT) {
659
+ this.topElement?.setZIndex()
660
+ element.setZIndex(ELEMENT_MAX_Z_INDEX)
661
+ this.topElement = element
662
+ }
663
+ if (this.overlapMode === OverlapMode.INCREASE) {
664
+ this.setElementZIndex(id, 'top')
665
+ }
666
+ }
667
+ }
668
+
669
+ /**
670
+ * 设置元素的zIndex.
671
+ * 注意:默认堆叠模式下,不建议使用此方法。
672
+ * @see todo link 堆叠模式
673
+ * @param id 元素id
674
+ * @param zIndex zIndex的值,可以传数字,也支持传入 'top' 和 'bottom'
675
+ */
676
+ @action
677
+ setElementZIndex(id: string, zIndex: number | 'top' | 'bottom') {
678
+ const element = this.nodesMap[id]?.model || this.edgesMap[id]?.model
679
+ if (element) {
680
+ let index: number
681
+ if (typeof zIndex === 'number') {
682
+ index = zIndex
683
+ } else {
684
+ if (zIndex === 'top') {
685
+ index = getZIndex()
686
+ }
687
+ if (zIndex === 'bottom') {
688
+ index = getMinIndex()
689
+ }
690
+ }
691
+ element.setZIndex(index!)
692
+ }
693
+ }
694
+
695
+ /**
696
+ * 删除节点
697
+ * @param {string} nodeId 节点Id
698
+ */
699
+ @action
700
+ deleteNode(nodeId: string) {
701
+ const nodeData = this.nodesMap[nodeId].model.getData()
702
+ this.deleteEdgeBySource(nodeId)
703
+ this.deleteEdgeByTarget(nodeId)
704
+ this.nodes.splice(this.nodesMap[nodeId].index, 1)
705
+ this.eventCenter.emit(EventType.NODE_DELETE, { data: nodeData })
706
+ }
707
+
708
+ /**
709
+ * 添加节点
710
+ * @param nodeConfig 节点配置
711
+ * @param eventType 新增节点事件类型,默认EventType.NODE_ADD, 在Dnd拖拽时,会传入EventType.NODE_DND_ADD
712
+ * @param event MouseEvent 鼠标事件
713
+ */
714
+ @action
715
+ addNode(
716
+ nodeConfig: NodeConfig,
717
+ eventType: EventType = EventType.NODE_ADD,
718
+ event?: MouseEvent,
719
+ ) {
720
+ const originNodeData = formatData(nodeConfig)
721
+ // 添加节点的时候,如果这个节点 id 已经存在,则采用新 id
722
+ const { id } = originNodeData
723
+ if (id && this.nodesMap[id]) {
724
+ delete originNodeData.id
725
+ }
726
+ const nodeModel = this.getModelAfterSnapToGrid(originNodeData)
727
+ this.nodes.push(nodeModel)
728
+ const nodeData = nodeModel.getData()
729
+ const eventData: Record<string, any> = { data: nodeData }
730
+ if (event) {
731
+ eventData.e = event
732
+ }
733
+ this.eventCenter.emit(eventType, eventData)
734
+ return nodeModel
735
+ }
736
+
737
+ /**
738
+ * 将node节点位置进行grid修正
739
+ * 同时处理node内文字的偏移量
740
+ * 返回一个位置修正过的复制节点NodeModel
741
+ * @param node
742
+ */
743
+ getModelAfterSnapToGrid(node: NodeConfig) {
744
+ const Model = this.getModel(node.type) as BaseNodeModelCtor
745
+ if (!Model) {
746
+ throw new Error(
747
+ `找不到${node.type}对应的节点,请确认是否已注册此类型节点。`,
748
+ )
749
+ }
750
+ const { x: nodeX, y: nodeY } = node
751
+ // 根据 grid 修正节点的 x, y
752
+ if (nodeX && nodeY) {
753
+ node.x = snapToGrid(nodeX, this.gridSize)
754
+ node.y = snapToGrid(nodeY, this.gridSize)
755
+ if (typeof node.text === 'object') {
756
+ // 原来的处理是:node.text.x -= getGridOffset(nodeX, this.gridSize)
757
+ // 由于snapToGrid()使用了Math.round()四舍五入的做法,因此无法判断需要执行
758
+ // node.text.x = node.text.x + getGridOffset()
759
+ // 还是
760
+ // node.text.x = node.text.x - getGridOffset()
761
+ // 直接改为node.x - nodeX就可以满足上面的要求
762
+ node.text.x += node.x - nodeX
763
+ node.text.y += node.y - nodeY
764
+ }
765
+ }
766
+ return new Model(node, this)
767
+ }
768
+
769
+ /**
770
+ * 克隆节点
771
+ * @param nodeId 节点Id
772
+ */
773
+ @action
774
+ cloneNode(nodeId: string) {
775
+ const targetNode = this.getNodeModelById(nodeId)
776
+ const data = targetNode?.getData()
777
+ if (data) {
778
+ data.x += 30
779
+ data.y += 30
780
+ data.id = ''
781
+ if (data.text) {
782
+ data.text.x += 30
783
+ data.text.y += 30
784
+ }
785
+ const nodeModel = this.addNode(data)
786
+ nodeModel.setSelected(true)
787
+ targetNode?.setSelected(false)
788
+ return nodeModel.getData()
789
+ }
790
+ }
791
+
792
+ /**
793
+ * 移动节点-相对位置
794
+ * @param nodeId 节点Id
795
+ * @param deltaX X轴移动距离
796
+ * @param deltaY Y轴移动距离
797
+ * @param isIgnoreRule 是否忽略移动规则限制
798
+ */
799
+ @action
800
+ moveNode(
801
+ nodeId: string,
802
+ deltaX: number,
803
+ deltaY: number,
804
+ isIgnoreRule = false,
805
+ ) {
806
+ // 1) 移动节点
807
+ const node = this.nodesMap[nodeId]
808
+ if (!node) {
809
+ console.warn(`不存在id为${nodeId}的节点`)
810
+ return
811
+ }
812
+ const nodeModel = node.model
813
+ ;[deltaX, deltaY] = nodeModel.getMoveDistance(deltaX, deltaY, isIgnoreRule)
814
+ // 2) 移动边
815
+ this.moveEdge(nodeId, deltaX, deltaY)
816
+ }
817
+
818
+ /**
819
+ * 移动节点-绝对位置
820
+ * @param nodeId 节点Id
821
+ * @param x X轴目标位置
822
+ * @param y Y轴目标位置
823
+ * @param isIgnoreRule 是否忽略条件,默认为 false
824
+ */
825
+ @action
826
+ moveNode2Coordinate(
827
+ nodeId: string,
828
+ x: number,
829
+ y: number,
830
+ isIgnoreRule = false,
831
+ ) {
832
+ // 1) 移动节点
833
+ const node = this.nodesMap[nodeId]
834
+ if (!node) {
835
+ console.warn(`不存在id为${nodeId}的节点`)
836
+ return
837
+ }
838
+ const nodeModel = node.model
839
+ const { x: originX, y: originY } = nodeModel
840
+ const deltaX = x - originX
841
+ const deltaY = y - originY
842
+ this.moveNode(nodeId, deltaX, deltaY, isIgnoreRule)
843
+ }
844
+
845
+ /**
846
+ * 显示节点、连线文本编辑框
847
+ * @param id 节点 or 连线 id
848
+ */
849
+ @action
850
+ editText(id: string) {
851
+ this.setElementStateById(id, ElementState.TEXT_EDIT)
852
+ }
853
+
854
+ /**
855
+ * 给两个节点之间添加一条边
856
+ * @param {object} edgeConfig
857
+ */
858
+ @action
859
+ addEdge(edgeConfig: LogicFlow.EdgeConfig): BaseEdgeModel {
860
+ const edgeOriginData = formatData(edgeConfig)
861
+ // 边的类型优先级:自定义>全局>默认
862
+ let { type } = edgeOriginData
863
+ if (!type) {
864
+ type = this.edgeType
865
+ }
866
+ if (edgeOriginData.id && this.edgesMap[edgeOriginData.id]) {
867
+ delete edgeOriginData.id
868
+ }
869
+ const Model = this.getModel(type) as BaseEdgeModelCtor
870
+ if (!Model) {
871
+ throw new Error(`找不到${type}对应的边,请确认是否已注册此类型边。`)
872
+ }
873
+ const edgeModel = new Model(
874
+ {
875
+ ...edgeOriginData,
876
+ type,
877
+ },
878
+ this,
879
+ )
880
+
881
+ const edgeData = edgeModel.getData()
882
+ this.edges.push(edgeModel)
883
+ this.eventCenter.emit(EventType.EDGE_ADD, { data: edgeData })
884
+ return edgeModel
885
+ }
886
+
887
+ /**
888
+ * 移动边,内部方法,请勿直接使用
889
+ */
890
+ @action
891
+ moveEdge(nodeId: string, deltaX: number, deltaY: number) {
892
+ /* 更新相关边位置 */
893
+ for (let i = 0; i < this.edges.length; i++) {
894
+ const edgeModel = this.edges[i]
895
+ const { x, y } = edgeModel.textPosition
896
+ const nodeAsSource = this.edges[i].sourceNodeId === nodeId
897
+ const nodeAsTarget = this.edges[i].targetNodeId === nodeId
898
+ if (nodeAsSource) {
899
+ edgeModel.moveStartPoint(deltaX, deltaY)
900
+ }
901
+ if (nodeAsTarget) {
902
+ edgeModel.moveEndPoint(deltaX, deltaY)
903
+ }
904
+ // 如果有文案了,当节点移动引起文案位置修改时,找出当前文案位置与最新边距离最短距离的点
905
+ // 最大程度保持节点位置不变且在边上
906
+ if (nodeAsSource || nodeAsTarget) {
907
+ this.handleEdgeTextMove(edgeModel, x, y)
908
+ }
909
+ }
910
+ }
911
+
912
+ /**
913
+ * 如果有文案了,当节点移动引起文案位置修改时,找出当前文案位置与最新边距离最短距离的点
914
+ * 最大程度保持节点位置不变且在边上
915
+ * @param edgeModel 边的数据管理类
916
+ * @param x X轴移动距离
917
+ * @param y Y轴移动距离
918
+ */
919
+ handleEdgeTextMove(edgeModel: BaseEdgeModel, x: number, y: number) {
920
+ // todo: 找到更好的边位置移动处理方式
921
+ // 如果是自定义边文本位置,则移动节点的时候重新计算其位置
922
+ if (edgeModel.customTextPosition) {
923
+ edgeModel.resetTextPosition()
924
+ } else if (
925
+ edgeModel.modelType === ModelType.POLYLINE_EDGE &&
926
+ edgeModel.text?.value
927
+ ) {
928
+ const textPosition = edgeModel.text
929
+ const newPoint = getClosestPointOfPolyline(textPosition, edgeModel.points)
930
+ edgeModel.moveText(
931
+ newPoint.x - textPosition.x,
932
+ newPoint.y - textPosition.y,
933
+ )
934
+ } else {
935
+ const { x: x1, y: y1 } = edgeModel.textPosition
936
+ edgeModel.moveText(x1 - x, y1 - y)
937
+ }
938
+ }
939
+
940
+ /**
941
+ * 删除两节点之间的边
942
+ * @param sourceNodeId 边的起始节点
943
+ * @param targetNodeId 边的目的节点
944
+ */
945
+ @action
946
+ deleteEdgeBySourceAndTarget(sourceNodeId: string, targetNodeId: string) {
947
+ for (let i = 0; i < this.edges.length; i++) {
948
+ if (
949
+ this.edges[i].sourceNodeId === sourceNodeId &&
950
+ this.edges[i].targetNodeId === targetNodeId
951
+ ) {
952
+ const edgeData = this.edges[i].getData()
953
+ this.edges.splice(i, 1)
954
+ i--
955
+ this.eventCenter.emit(EventType.EDGE_DELETE, { data: edgeData })
956
+ }
957
+ }
958
+ }
959
+
960
+ /**
961
+ * 基于边Id删除边
962
+ */
963
+ @action
964
+ deleteEdgeById(id: string) {
965
+ const edge = this.edgesMap[id]
966
+ if (!edge) {
967
+ return
968
+ }
969
+ const idx = this.edgesMap[id].index
970
+ const edgeData = this.edgesMap[id].model.getData()
971
+ this.edges.splice(idx, 1)
972
+ this.eventCenter.emit(EventType.EDGE_DELETE, { data: edgeData })
973
+ }
974
+
975
+ /**
976
+ * 删除以节点Id为起点的所有边
977
+ */
978
+ @action
979
+ deleteEdgeBySource(sourceNodeId: string) {
980
+ for (let i = 0; i < this.edges.length; i++) {
981
+ if (this.edges[i].sourceNodeId === sourceNodeId) {
982
+ const edgeData = this.edges[i].getData()
983
+ this.edges.splice(i, 1)
984
+ i--
985
+ this.eventCenter.emit(EventType.EDGE_DELETE, { data: edgeData })
986
+ }
987
+ }
988
+ }
989
+
990
+ /**
991
+ * 删除以节点Id为终点的所有边
992
+ */
993
+ @action
994
+ deleteEdgeByTarget(targetNodeId: string) {
995
+ for (let i = 0; i < this.edges.length; i++) {
996
+ if (this.edges[i].targetNodeId === targetNodeId) {
997
+ const edgeData = this.edges[i].getData()
998
+ this.edges.splice(i, 1)
999
+ i--
1000
+ this.eventCenter.emit(EventType.EDGE_DELETE, { data: edgeData })
1001
+ }
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * 设置元素的状态,在需要保证整个画布上所有的元素只有一个元素拥有此状态时可以调用此方法。
1007
+ * 例如文本编辑、菜单显示等。
1008
+ * additionStateData: 传递的额外值,如菜单显示的时候,需要传递期望菜单显示的位置。
1009
+ */
1010
+ @action
1011
+ setElementStateById(
1012
+ id: string,
1013
+ state: ElementState,
1014
+ additionStateData?: Model.AdditionStateDataType,
1015
+ ) {
1016
+ this.nodes.forEach((node) => {
1017
+ if (node.id === id) {
1018
+ node.setElementState(state, additionStateData)
1019
+ } else {
1020
+ node.setElementState(ElementState.DEFAULT)
1021
+ }
1022
+ })
1023
+ this.edges.forEach((edge) => {
1024
+ if (edge.id === id) {
1025
+ edge.setElementState(state, additionStateData)
1026
+ } else {
1027
+ edge.setElementState(ElementState.DEFAULT)
1028
+ }
1029
+ })
1030
+ }
1031
+
1032
+ /**
1033
+ * 更新节点或边的文案
1034
+ * @param id 节点或者边id
1035
+ * @param value 文案内容
1036
+ */
1037
+ @action
1038
+ updateText(id: string, value: string) {
1039
+ const element = find(
1040
+ [...this.nodes, ...this.edges],
1041
+ (item) => item.id === id,
1042
+ )
1043
+ element?.updateText(value)
1044
+ }
1045
+
1046
+ /**
1047
+ * 选中节点
1048
+ * @param id 节点Id
1049
+ * @param multiple 是否为多选,如果为多选,则不去掉原有已选择节点的选中状态
1050
+ */
1051
+ @action selectNodeById(id: string, multiple = false) {
1052
+ if (!multiple) {
1053
+ this.clearSelectElements()
1054
+ }
1055
+ const selectElement = this.nodesMap[id]?.model
1056
+ selectElement?.setSelected(true)
1057
+ }
1058
+
1059
+ /**
1060
+ * 选中边
1061
+ * @param id 边Id
1062
+ * @param multiple 是否为多选,如果为多选,则不去掉原已选中边的状态
1063
+ */
1064
+ @action selectEdgeById(id: string, multiple = false) {
1065
+ if (!multiple) {
1066
+ this.clearSelectElements()
1067
+ }
1068
+ const selectElement = this.edgesMap[id]?.model
1069
+ selectElement?.setSelected(true)
1070
+ }
1071
+
1072
+ /**
1073
+ * 将图形选中
1074
+ * @param id 选择元素ID
1075
+ * @param multiple 是否允许多选,如果为true,不会将上一个选中的元素重置
1076
+ */
1077
+ @action
1078
+ selectElementById(id: string, multiple = false) {
1079
+ if (!multiple) {
1080
+ this.clearSelectElements()
1081
+ }
1082
+ const selectElement = this.getElement(id)
1083
+ selectElement?.setSelected(true)
1084
+ }
1085
+
1086
+ /**
1087
+ * 将所有选中的元素设置为非选中
1088
+ */
1089
+ @action
1090
+ clearSelectElements() {
1091
+ this.selectElements.forEach((element) => {
1092
+ element?.setSelected(false)
1093
+ })
1094
+ this.selectElements.clear()
1095
+ /**
1096
+ * 如果堆叠模式为默认模式,则将置顶元素重新恢复原有层级
1097
+ */
1098
+ if (this.overlapMode === OverlapMode.DEFAULT) {
1099
+ this.topElement?.setZIndex()
1100
+ }
1101
+ }
1102
+
1103
+ /**
1104
+ * 批量移动节点,节点移动的时候,会动态计算所有节点与未移动节点的边位置
1105
+ * 移动的节点之间的边会保持相对位置
1106
+ */
1107
+ @action
1108
+ moveNodes(
1109
+ nodeIds: string[],
1110
+ deltaX: number,
1111
+ deltaY: number,
1112
+ isIgnoreRule = false,
1113
+ ) {
1114
+ // FIX: https://github.com/didi/LogicFlow/issues/1015
1115
+ // 如果节点之间存在连线,则只移动连线一次。
1116
+ const nodeIdMap: Record<string, [number, number]> = nodeIds.reduce(
1117
+ (acc, cur) => {
1118
+ const nodeModel = this.nodesMap[cur].model
1119
+ acc[cur] = nodeModel.getMoveDistance(deltaX, deltaY, isIgnoreRule)
1120
+ return acc
1121
+ },
1122
+ {},
1123
+ )
1124
+ for (let i = 0; i < this.edges.length; i++) {
1125
+ const edgeModel = this.edges[i]
1126
+ const { x, y } = edgeModel.textPosition
1127
+ const sourceMoveDistance = nodeIdMap[edgeModel.sourceNodeId]
1128
+ const targetMoveDistance = nodeIdMap[edgeModel.targetNodeId]
1129
+ let textDistanceX: number
1130
+ let textDistanceY: number
1131
+ if (
1132
+ sourceMoveDistance &&
1133
+ targetMoveDistance &&
1134
+ edgeModel.modelType === ModelType.POLYLINE_EDGE
1135
+ ) {
1136
+ // 移动框选区时,如果边polyline在框选范围内,则边的轨迹pointsList也要整体移动
1137
+ ;[textDistanceX, textDistanceY] = sourceMoveDistance
1138
+ ;(edgeModel as PolylineEdgeModel).updatePointsList(
1139
+ textDistanceX,
1140
+ textDistanceY,
1141
+ )
1142
+ } else {
1143
+ if (sourceMoveDistance) {
1144
+ ;[textDistanceX, textDistanceY] = sourceMoveDistance
1145
+ edgeModel.moveStartPoint(textDistanceX, textDistanceY)
1146
+ }
1147
+ if (targetMoveDistance) {
1148
+ ;[textDistanceX, textDistanceY] = targetMoveDistance
1149
+ edgeModel.moveEndPoint(textDistanceX, textDistanceY)
1150
+ }
1151
+ }
1152
+ if (sourceMoveDistance || targetMoveDistance) {
1153
+ // https://github.com/didi/LogicFlow/issues/1191
1154
+ // moveNode()跟moveNodes()没有统一处理方式,moveNodes()缺失了下面的逻辑
1155
+ // moveNode():当节点移动引起文案位置修改时,找出当前文案位置与最新边距离最短距离的点,最大程度保持节点位置不变且在边上
1156
+ // 因此将moveNode()处理边文字的逻辑抽离出来,统一moveNode()跟moveNodes()的处理逻辑
1157
+ this.handleEdgeTextMove(edgeModel, x, y)
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ /**
1163
+ * 添加节点移动限制规则,在节点移动的时候触发。
1164
+ * 如果方法返回false, 则会阻止节点移动。
1165
+ * @param fn function
1166
+ * @example
1167
+ *
1168
+ * graphModel.addNodeMoveRules((nodeModel, x, y) => {
1169
+ * if (nodeModel.properties.disabled) {
1170
+ * return false
1171
+ * }
1172
+ * return true
1173
+ * })
1174
+ *
1175
+ */
1176
+ addNodeMoveRules(fn: Model.NodeMoveRule) {
1177
+ if (!this.nodeMoveRules.includes(fn)) {
1178
+ this.nodeMoveRules.push(fn)
1179
+ }
1180
+ }
1181
+
1182
+ /**
1183
+ * 设置默认的边类型
1184
+ * 也就是设置在节点直接有用户手动绘制的连线类型。
1185
+ * @param type LFOptions.EdgeType
1186
+ */
1187
+ @action
1188
+ setDefaultEdgeType(type: LFOptions.EdgeType): void {
1189
+ this.edgeType = type
1190
+ }
1191
+
1192
+ /**
1193
+ * 修改指定节点类型
1194
+ * @param id 节点id
1195
+ * @param type 节点类型
1196
+ */
1197
+ @action
1198
+ changeNodeType(id: string, type: string): void {
1199
+ const nodeModel = this.getNodeModelById(id)
1200
+ if (!nodeModel) {
1201
+ console.warn(`找不到id为${id}的节点`)
1202
+ return
1203
+ }
1204
+ const data = nodeModel.getData()
1205
+ data.type = type
1206
+ const Model = this.getModel(type) as BaseNodeModelCtor
1207
+ if (!Model) {
1208
+ throw new Error(`找不到${type}对应的节点,请确认是否已注册此类型节点。`)
1209
+ }
1210
+ const newNodeModel = new Model(data, this)
1211
+ this.nodes.splice(this.nodesMap[id].index, 1, newNodeModel)
1212
+ // 微调边
1213
+ const edgeModels = this.getNodeEdges(id)
1214
+ edgeModels.forEach((edge) => {
1215
+ if (edge.sourceNodeId === id) {
1216
+ const point = getNodeAnchorPosition(
1217
+ newNodeModel,
1218
+ edge.startPoint,
1219
+ newNodeModel.width,
1220
+ newNodeModel.height,
1221
+ )
1222
+ edge.updateStartPoint(point)
1223
+ }
1224
+ if (edge.targetNodeId === id) {
1225
+ const point = getNodeAnchorPosition(
1226
+ newNodeModel,
1227
+ edge.endPoint,
1228
+ newNodeModel.width,
1229
+ newNodeModel.height,
1230
+ )
1231
+ edge.updateEndPoint(point)
1232
+ }
1233
+ })
1234
+ }
1235
+
1236
+ /**
1237
+ * 切换边的类型
1238
+ * @param id 边Id
1239
+ * @param type 边类型
1240
+ */
1241
+ @action changeEdgeType(id: string, type: LFOptions.EdgeType) {
1242
+ const edgeModel = this.getEdgeModelById(id)
1243
+ if (!edgeModel) {
1244
+ console.warn(`找不到id为${id}的边`)
1245
+ return
1246
+ }
1247
+ if (edgeModel.type === type) {
1248
+ return
1249
+ }
1250
+ const data = edgeModel.getData()
1251
+ data.type = type
1252
+ const Model = this.getModel(type) as BaseEdgeModelCtor
1253
+ if (!Model) {
1254
+ throw new Error(`找不到${type}对应的节点,请确认是否已注册此类型节点。`)
1255
+ }
1256
+ // 为了保持切换类型时不复用上一个类型的轨迹
1257
+ delete data.pointsList
1258
+ const newEdgeModel = new Model(data, this)
1259
+ this.edges.splice(this.edgesMap[id].index, 1, newEdgeModel)
1260
+ }
1261
+
1262
+ /**
1263
+ * 获取所有以此节点为终点的边
1264
+ */
1265
+ @action getNodeIncomingEdge(nodeId: string) {
1266
+ const edges: BaseEdgeModel[] = []
1267
+ this.edges.forEach((edge) => {
1268
+ if (edge.targetNodeId === nodeId) {
1269
+ edges.push(edge)
1270
+ }
1271
+ })
1272
+ return edges
1273
+ }
1274
+
1275
+ /**
1276
+ * 获取所有以此节点为起点的边
1277
+ */
1278
+ @action getNodeOutgoingEdge(nodeId: string) {
1279
+ const edges: BaseEdgeModel[] = []
1280
+ this.edges.forEach((edge) => {
1281
+ if (edge.sourceNodeId === nodeId) {
1282
+ edges.push(edge)
1283
+ }
1284
+ })
1285
+ return edges
1286
+ }
1287
+
1288
+ /**
1289
+ * 获取所有以此锚点为终点的边
1290
+ */
1291
+ @action getAnchorIncomingEdge(anchorId?: string) {
1292
+ const edges: BaseEdgeModel[] = []
1293
+ this.edges.forEach((edge) => {
1294
+ if (edge.targetAnchorId === anchorId) {
1295
+ edges.push(edge)
1296
+ }
1297
+ })
1298
+ return edges
1299
+ }
1300
+
1301
+ /**
1302
+ * TODO: 命名问题 outcoming -> outgoing or incoming
1303
+ * 获取所有以此锚点为起点的边
1304
+ */
1305
+ @action getAnchorOutcomingEdge(anchorId?: string) {
1306
+ const edges: BaseEdgeModel[] = []
1307
+ this.edges.forEach((edge) => {
1308
+ if (edge.sourceAnchorId === anchorId) {
1309
+ edges.push(edge)
1310
+ }
1311
+ })
1312
+ return edges
1313
+ }
1314
+
1315
+ /**
1316
+ * 获取节点连接到的所有起始节点
1317
+ */
1318
+ @action getNodeIncomingNode(nodeId?: string) {
1319
+ const nodes: BaseNodeModel[] = []
1320
+ this.edges.forEach((edge) => {
1321
+ if (edge.targetNodeId === nodeId) {
1322
+ nodes.push(this.nodesMap[edge.sourceNodeId]?.model)
1323
+ }
1324
+ })
1325
+ return nodes
1326
+ }
1327
+
1328
+ /**
1329
+ * 获取节点连接到的所有目标节点
1330
+ */
1331
+ @action getNodeOutgoingNode(nodeId?: string) {
1332
+ const nodes: BaseNodeModel[] = []
1333
+ this.edges.forEach((edge) => {
1334
+ if (edge.sourceNodeId === nodeId) {
1335
+ nodes.push(this.nodesMap[edge.targetNodeId].model)
1336
+ }
1337
+ })
1338
+ return nodes
1339
+ }
1340
+
1341
+ /**
1342
+ * 设置主题
1343
+ * todo docs link
1344
+ */
1345
+ @action setTheme(style: Partial<LogicFlow.Theme>) {
1346
+ this.theme = updateTheme({ ...this.theme, ...style })
1347
+ }
1348
+
1349
+ /**
1350
+ * 重新设置画布的宽高
1351
+ */
1352
+ @action resize(width?: number, height?: number): void {
1353
+ this.width = width || this.rootEl.getBoundingClientRect().width
1354
+ this.height = height || this.rootEl.getBoundingClientRect().height
1355
+ if (!this.width || !this.height) {
1356
+ console.warn(
1357
+ '渲染画布的时候无法获取画布宽高,请确认在container已挂载到DOM。@see https://github.com/didi/LogicFlow/issues/675',
1358
+ )
1359
+ }
1360
+ }
1361
+
1362
+ /**
1363
+ * 清空画布
1364
+ */
1365
+ @action clearData(): void {
1366
+ this.nodes = []
1367
+ this.edges = []
1368
+ }
1369
+
1370
+ /**
1371
+ * 获取图形区域虚拟矩型的尺寸和中心坐标
1372
+ * @returns
1373
+ */
1374
+ getVirtualRectSize(): GraphModel.VirtualRectProps {
1375
+ const { nodes } = this
1376
+ let nodesX: number[] = []
1377
+ let nodesY: number[] = []
1378
+ // 获取所有节点组成的x,y轴最大最小值,这里考虑了图形的长宽和边框
1379
+ nodes.forEach((node) => {
1380
+ const { x, y, width, height } = node
1381
+ const { strokeWidth = 0 } = node.getNodeStyle()
1382
+ const maxX = x + width / 2 + strokeWidth
1383
+ const minX = x - width / 2 - strokeWidth
1384
+ const maxY = y + height / 2 + strokeWidth
1385
+ const minY = y - height / 2 - strokeWidth
1386
+ nodesX = nodesX.concat([maxX, minX].filter((num) => !Number.isNaN(num)))
1387
+ nodesY = nodesY.concat([maxY, minY].filter((num) => !Number.isNaN(num)))
1388
+ })
1389
+
1390
+ const minX = Math.min(...nodesX)
1391
+ const maxX = Math.max(...nodesX)
1392
+ const minY = Math.min(...nodesY)
1393
+ const maxY = Math.max(...nodesY)
1394
+
1395
+ const virtualRectWidth = maxX - minX || 0
1396
+ const virtualRectHeight = maxY - minY || 0
1397
+
1398
+ // 获取虚拟矩型的中心坐标
1399
+ const virtualRectCenterPositionX = minX + virtualRectWidth / 2
1400
+ const virtualRectCenterPositionY = minY + virtualRectHeight / 2
1401
+
1402
+ return {
1403
+ width: virtualRectWidth,
1404
+ height: virtualRectHeight,
1405
+ x: virtualRectCenterPositionX,
1406
+ y: virtualRectCenterPositionY,
1407
+ }
1408
+ }
1409
+
1410
+ /**
1411
+ * 将图形整体移动到画布中心
1412
+ */
1413
+ @action translateCenter(): void {
1414
+ const { nodes, width, height, rootEl, transformModel } = this
1415
+ if (!nodes.length) {
1416
+ return
1417
+ }
1418
+
1419
+ const containerWidth = width || rootEl.clientWidth
1420
+ const containerHeight = height || rootEl.clientHeight
1421
+
1422
+ const { x: virtualRectCenterPositionX, y: virtualRectCenterPositionY } =
1423
+ this.getVirtualRectSize()
1424
+
1425
+ // 将虚拟矩型移动到画布中心
1426
+ transformModel.focusOn(
1427
+ virtualRectCenterPositionX,
1428
+ virtualRectCenterPositionY,
1429
+ containerWidth,
1430
+ containerHeight,
1431
+ )
1432
+ }
1433
+
1434
+ /**
1435
+ * 画布图形适应屏幕大小
1436
+ * @param verticalOffset number 距离盒子上下的距离, 默认为20
1437
+ * @param horizontalOffset number 距离盒子左右的距离, 默认为20
1438
+ */
1439
+ @action fitView(verticalOffset = 20, horizontalOffset = 20): void {
1440
+ const { nodes, width, height, rootEl, transformModel } = this
1441
+ if (!nodes.length) {
1442
+ return
1443
+ }
1444
+ const containerWidth = width || rootEl.clientWidth
1445
+ const containerHeight = height || rootEl.clientHeight
1446
+
1447
+ const {
1448
+ width: virtualRectWidth,
1449
+ height: virtualRectHeight,
1450
+ x: virtualRectCenterPositionX,
1451
+ y: virtualRectCenterPositionY,
1452
+ } = this.getVirtualRectSize()
1453
+
1454
+ const zoomRatioX = (virtualRectWidth + horizontalOffset) / containerWidth
1455
+ const zoomRatioY = (virtualRectHeight + verticalOffset) / containerHeight
1456
+ const zoomRatio = 1 / Math.max(zoomRatioX, zoomRatioY)
1457
+
1458
+ const point: PointTuple = [containerWidth / 2, containerHeight / 2]
1459
+ // 适应画布大小
1460
+ transformModel.zoom(zoomRatio, point)
1461
+ // 将虚拟矩型移动到画布中心
1462
+ transformModel.focusOn(
1463
+ virtualRectCenterPositionX,
1464
+ virtualRectCenterPositionY,
1465
+ containerWidth,
1466
+ containerHeight,
1467
+ )
1468
+ }
1469
+
1470
+ /**
1471
+ * 开启边的动画
1472
+ * @param edgeId string
1473
+ */
1474
+ @action openEdgeAnimation(edgeId: string): void {
1475
+ const edgeModel = this.getEdgeModelById(edgeId)
1476
+ edgeModel?.openEdgeAnimation()
1477
+ }
1478
+
1479
+ /**
1480
+ * 关闭边的动画
1481
+ * @param edgeId string
1482
+ */
1483
+ @action closeEdgeAnimation(edgeId: string): void {
1484
+ const edgeModel = this.getEdgeModelById(edgeId)
1485
+ edgeModel?.closeEdgeAnimation()
1486
+ }
1487
+ }
1488
+
1489
+ export namespace GraphModel {
1490
+ export type NodesMapType = Record<
1491
+ string,
1492
+ {
1493
+ index: number
1494
+ model: BaseNodeModel
1495
+ }
1496
+ >
1497
+ export type EdgesMapType = Record<
1498
+ string,
1499
+ {
1500
+ index: number
1501
+ model: BaseEdgeModel
1502
+ }
1503
+ >
1504
+
1505
+ export type ModelsMapType = Record<string, BaseNodeModel | BaseEdgeModel>
1506
+
1507
+ // 虚拟矩阵信息类型
1508
+ export type VirtualRectProps = {
1509
+ width: number
1510
+ height: number
1511
+ x: number
1512
+ y: number
1513
+ }
1514
+ }
1515
+
1516
+ export default GraphModel