@antv/layout 0.2.0 → 0.2.3

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 (297) hide show
  1. package/dist/layout.min.js +1 -1
  2. package/dist/layout.min.js.LICENSE.txt +0 -9
  3. package/dist/layout.min.js.map +1 -1
  4. package/es/layout/circular.js.map +1 -1
  5. package/es/layout/comboCombined.js +3 -19
  6. package/es/layout/comboCombined.js.map +1 -1
  7. package/es/layout/concentric.js.map +1 -1
  8. package/es/layout/dagre/graph.d.ts +91 -0
  9. package/es/layout/dagre/graph.js +4 -0
  10. package/es/layout/dagre/graph.js.map +1 -0
  11. package/es/layout/dagre/index.d.ts +3 -4
  12. package/es/layout/dagre/index.js +0 -2
  13. package/es/layout/dagre/index.js.map +1 -1
  14. package/es/layout/dagre/src/acyclic.d.ts +1 -2
  15. package/es/layout/dagre/src/acyclic.js +7 -7
  16. package/es/layout/dagre/src/acyclic.js.map +1 -1
  17. package/es/layout/dagre/src/add-border-segments.d.ts +1 -2
  18. package/es/layout/dagre/src/add-border-segments.js +5 -5
  19. package/es/layout/dagre/src/add-border-segments.js.map +1 -1
  20. package/es/layout/dagre/src/coordinate-system.d.ts +1 -2
  21. package/es/layout/dagre/src/coordinate-system.js +15 -5
  22. package/es/layout/dagre/src/coordinate-system.js.map +1 -1
  23. package/es/layout/dagre/src/data/list.d.ts +9 -5
  24. package/es/layout/dagre/src/data/list.js +25 -27
  25. package/es/layout/dagre/src/data/list.js.map +1 -1
  26. package/es/layout/dagre/src/debug.d.ts +2 -3
  27. package/es/layout/dagre/src/debug.js +3 -5
  28. package/es/layout/dagre/src/debug.js.map +1 -1
  29. package/es/layout/dagre/src/greedy-fas.d.ts +2 -3
  30. package/es/layout/dagre/src/greedy-fas.js +16 -15
  31. package/es/layout/dagre/src/greedy-fas.js.map +1 -1
  32. package/es/layout/dagre/src/layout.d.ts +2 -3
  33. package/es/layout/dagre/src/layout.js +170 -91
  34. package/es/layout/dagre/src/layout.js.map +1 -1
  35. package/es/layout/dagre/src/nesting-graph.d.ts +1 -2
  36. package/es/layout/dagre/src/nesting-graph.js +15 -10
  37. package/es/layout/dagre/src/nesting-graph.js.map +1 -1
  38. package/es/layout/dagre/src/normalize.d.ts +1 -2
  39. package/es/layout/dagre/src/normalize.js +12 -11
  40. package/es/layout/dagre/src/normalize.js.map +1 -1
  41. package/es/layout/dagre/src/order/add-subgraph-constraints.d.ts +1 -2
  42. package/es/layout/dagre/src/order/add-subgraph-constraints.js.map +1 -1
  43. package/es/layout/dagre/src/order/barycenter.d.ts +1 -2
  44. package/es/layout/dagre/src/order/barycenter.js.map +1 -1
  45. package/es/layout/dagre/src/order/build-layer-graph.d.ts +2 -3
  46. package/es/layout/dagre/src/order/build-layer-graph.js +12 -8
  47. package/es/layout/dagre/src/order/build-layer-graph.js.map +1 -1
  48. package/es/layout/dagre/src/order/cross-count.d.ts +2 -3
  49. package/es/layout/dagre/src/order/cross-count.js +13 -12
  50. package/es/layout/dagre/src/order/cross-count.js.map +1 -1
  51. package/es/layout/dagre/src/order/index.d.ts +2 -3
  52. package/es/layout/dagre/src/order/index.js +17 -15
  53. package/es/layout/dagre/src/order/index.js.map +1 -1
  54. package/es/layout/dagre/src/order/init-data-order.d.ts +1 -2
  55. package/es/layout/dagre/src/order/init-data-order.js +3 -5
  56. package/es/layout/dagre/src/order/init-data-order.js.map +1 -1
  57. package/es/layout/dagre/src/order/init-order.d.ts +2 -3
  58. package/es/layout/dagre/src/order/init-order.js +1 -2
  59. package/es/layout/dagre/src/order/init-order.js.map +1 -1
  60. package/es/layout/dagre/src/order/resolve-conflicts.d.ts +18 -3
  61. package/es/layout/dagre/src/order/resolve-conflicts.js +9 -29
  62. package/es/layout/dagre/src/order/resolve-conflicts.js.map +1 -1
  63. package/es/layout/dagre/src/order/sort-subgraph.d.ts +6 -3
  64. package/es/layout/dagre/src/order/sort-subgraph.js +19 -14
  65. package/es/layout/dagre/src/order/sort-subgraph.js.map +1 -1
  66. package/es/layout/dagre/src/order/sort.d.ts +6 -1
  67. package/es/layout/dagre/src/order/sort.js +2 -2
  68. package/es/layout/dagre/src/order/sort.js.map +1 -1
  69. package/es/layout/dagre/src/parent-dummy-chains.d.ts +1 -2
  70. package/es/layout/dagre/src/parent-dummy-chains.js +47 -44
  71. package/es/layout/dagre/src/parent-dummy-chains.js.map +1 -1
  72. package/es/layout/dagre/src/position/bk.d.ts +22 -31
  73. package/es/layout/dagre/src/position/bk.js +49 -83
  74. package/es/layout/dagre/src/position/bk.js.map +1 -1
  75. package/es/layout/dagre/src/position/index.d.ts +1 -2
  76. package/es/layout/dagre/src/position/index.js +12 -14
  77. package/es/layout/dagre/src/position/index.js.map +1 -1
  78. package/es/layout/dagre/src/rank/feasible-tree.d.ts +5 -6
  79. package/es/layout/dagre/src/rank/feasible-tree.js +1 -2
  80. package/es/layout/dagre/src/rank/feasible-tree.js.map +1 -1
  81. package/es/layout/dagre/src/rank/index.d.ts +2 -3
  82. package/es/layout/dagre/src/rank/index.js.map +1 -1
  83. package/es/layout/dagre/src/rank/network-simplex.d.ts +8 -11
  84. package/es/layout/dagre/src/rank/network-simplex.js +18 -31
  85. package/es/layout/dagre/src/rank/network-simplex.js.map +1 -1
  86. package/es/layout/dagre/src/rank/util.d.ts +4 -5
  87. package/es/layout/dagre/src/rank/util.js +37 -20
  88. package/es/layout/dagre/src/rank/util.js.map +1 -1
  89. package/es/layout/dagre/src/util.d.ts +29 -48
  90. package/es/layout/dagre/src/util.js +91 -101
  91. package/es/layout/dagre/src/util.js.map +1 -1
  92. package/es/layout/dagre.d.ts +1 -1
  93. package/es/layout/dagre.js +28 -24
  94. package/es/layout/dagre.js.map +1 -1
  95. package/es/layout/fruchterman.js.map +1 -1
  96. package/es/layout/gForce.js +14 -6
  97. package/es/layout/gForce.js.map +1 -1
  98. package/lib/index.js +5 -1
  99. package/lib/index.js.map +1 -1
  100. package/lib/layout/circular.js.map +1 -1
  101. package/lib/layout/comboCombined.js +2 -18
  102. package/lib/layout/comboCombined.js.map +1 -1
  103. package/lib/layout/comboForce.js +5 -5
  104. package/lib/layout/comboForce.js.map +1 -1
  105. package/lib/layout/concentric.js.map +1 -1
  106. package/lib/layout/dagre/graph.d.ts +91 -0
  107. package/lib/layout/dagre/graph.js +28 -0
  108. package/lib/layout/dagre/graph.js.map +1 -0
  109. package/lib/layout/dagre/index.d.ts +3 -4
  110. package/lib/layout/dagre/index.js +0 -2
  111. package/lib/layout/dagre/index.js.map +1 -1
  112. package/lib/layout/dagre/src/acyclic.d.ts +1 -2
  113. package/lib/layout/dagre/src/acyclic.js +7 -7
  114. package/lib/layout/dagre/src/acyclic.js.map +1 -1
  115. package/lib/layout/dagre/src/add-border-segments.d.ts +1 -2
  116. package/lib/layout/dagre/src/add-border-segments.js +5 -8
  117. package/lib/layout/dagre/src/add-border-segments.js.map +1 -1
  118. package/lib/layout/dagre/src/coordinate-system.d.ts +1 -2
  119. package/lib/layout/dagre/src/coordinate-system.js +15 -5
  120. package/lib/layout/dagre/src/coordinate-system.js.map +1 -1
  121. package/lib/layout/dagre/src/data/list.d.ts +9 -5
  122. package/lib/layout/dagre/src/data/list.js +25 -26
  123. package/lib/layout/dagre/src/data/list.js.map +1 -1
  124. package/lib/layout/dagre/src/debug.d.ts +2 -3
  125. package/lib/layout/dagre/src/debug.js +6 -11
  126. package/lib/layout/dagre/src/debug.js.map +1 -1
  127. package/lib/layout/dagre/src/greedy-fas.d.ts +2 -3
  128. package/lib/layout/dagre/src/greedy-fas.js +41 -15
  129. package/lib/layout/dagre/src/greedy-fas.js.map +1 -1
  130. package/lib/layout/dagre/src/layout.d.ts +2 -3
  131. package/lib/layout/dagre/src/layout.js +171 -100
  132. package/lib/layout/dagre/src/layout.js.map +1 -1
  133. package/lib/layout/dagre/src/nesting-graph.d.ts +1 -2
  134. package/lib/layout/dagre/src/nesting-graph.js +15 -13
  135. package/lib/layout/dagre/src/nesting-graph.js.map +1 -1
  136. package/lib/layout/dagre/src/normalize.d.ts +1 -2
  137. package/lib/layout/dagre/src/normalize.js +12 -14
  138. package/lib/layout/dagre/src/normalize.js.map +1 -1
  139. package/lib/layout/dagre/src/order/add-subgraph-constraints.d.ts +1 -2
  140. package/lib/layout/dagre/src/order/add-subgraph-constraints.js.map +1 -1
  141. package/lib/layout/dagre/src/order/barycenter.d.ts +1 -2
  142. package/lib/layout/dagre/src/order/barycenter.js.map +1 -1
  143. package/lib/layout/dagre/src/order/build-layer-graph.d.ts +2 -3
  144. package/lib/layout/dagre/src/order/build-layer-graph.js +13 -12
  145. package/lib/layout/dagre/src/order/build-layer-graph.js.map +1 -1
  146. package/lib/layout/dagre/src/order/cross-count.d.ts +2 -3
  147. package/lib/layout/dagre/src/order/cross-count.js +14 -13
  148. package/lib/layout/dagre/src/order/cross-count.js.map +1 -1
  149. package/lib/layout/dagre/src/order/index.d.ts +2 -3
  150. package/lib/layout/dagre/src/order/index.js +15 -13
  151. package/lib/layout/dagre/src/order/index.js.map +1 -1
  152. package/lib/layout/dagre/src/order/init-data-order.d.ts +1 -2
  153. package/lib/layout/dagre/src/order/init-data-order.js +3 -5
  154. package/lib/layout/dagre/src/order/init-data-order.js.map +1 -1
  155. package/lib/layout/dagre/src/order/init-order.d.ts +2 -3
  156. package/lib/layout/dagre/src/order/init-order.js +1 -2
  157. package/lib/layout/dagre/src/order/init-order.js.map +1 -1
  158. package/lib/layout/dagre/src/order/resolve-conflicts.d.ts +18 -3
  159. package/lib/layout/dagre/src/order/resolve-conflicts.js +9 -29
  160. package/lib/layout/dagre/src/order/resolve-conflicts.js.map +1 -1
  161. package/lib/layout/dagre/src/order/sort-subgraph.d.ts +6 -3
  162. package/lib/layout/dagre/src/order/sort-subgraph.js +16 -11
  163. package/lib/layout/dagre/src/order/sort-subgraph.js.map +1 -1
  164. package/lib/layout/dagre/src/order/sort.d.ts +6 -1
  165. package/lib/layout/dagre/src/order/sort.js +2 -5
  166. package/lib/layout/dagre/src/order/sort.js.map +1 -1
  167. package/lib/layout/dagre/src/parent-dummy-chains.d.ts +1 -2
  168. package/lib/layout/dagre/src/parent-dummy-chains.js +47 -44
  169. package/lib/layout/dagre/src/parent-dummy-chains.js.map +1 -1
  170. package/lib/layout/dagre/src/position/bk.d.ts +22 -31
  171. package/lib/layout/dagre/src/position/bk.js +75 -85
  172. package/lib/layout/dagre/src/position/bk.js.map +1 -1
  173. package/lib/layout/dagre/src/position/index.d.ts +1 -2
  174. package/lib/layout/dagre/src/position/index.js +14 -17
  175. package/lib/layout/dagre/src/position/index.js.map +1 -1
  176. package/lib/layout/dagre/src/rank/feasible-tree.d.ts +5 -6
  177. package/lib/layout/dagre/src/rank/feasible-tree.js +3 -7
  178. package/lib/layout/dagre/src/rank/feasible-tree.js.map +1 -1
  179. package/lib/layout/dagre/src/rank/index.d.ts +2 -3
  180. package/lib/layout/dagre/src/rank/index.js.map +1 -1
  181. package/lib/layout/dagre/src/rank/network-simplex.d.ts +8 -11
  182. package/lib/layout/dagre/src/rank/network-simplex.js +27 -35
  183. package/lib/layout/dagre/src/rank/network-simplex.js.map +1 -1
  184. package/lib/layout/dagre/src/rank/util.d.ts +4 -5
  185. package/lib/layout/dagre/src/rank/util.js +36 -19
  186. package/lib/layout/dagre/src/rank/util.js.map +1 -1
  187. package/lib/layout/dagre/src/util.d.ts +29 -48
  188. package/lib/layout/dagre/src/util.js +80 -92
  189. package/lib/layout/dagre/src/util.js.map +1 -1
  190. package/lib/layout/dagre.d.ts +1 -1
  191. package/lib/layout/dagre.js +27 -23
  192. package/lib/layout/dagre.js.map +1 -1
  193. package/lib/layout/er/core.js +5 -1
  194. package/lib/layout/er/core.js.map +1 -1
  195. package/lib/layout/force/force-in-a-box.js +7 -3
  196. package/lib/layout/force/force-in-a-box.js.map +1 -1
  197. package/lib/layout/force/force.js +5 -1
  198. package/lib/layout/force/force.js.map +1 -1
  199. package/lib/layout/force/index.js +5 -1
  200. package/lib/layout/force/index.js.map +1 -1
  201. package/lib/layout/fruchterman.js.map +1 -1
  202. package/lib/layout/gForce.js +10 -2
  203. package/lib/layout/gForce.js.map +1 -1
  204. package/lib/layout/grid.js +2 -2
  205. package/lib/layout/grid.js.map +1 -1
  206. package/lib/layout/index.js +5 -1
  207. package/lib/layout/index.js.map +1 -1
  208. package/lib/layout/radial/index.js +5 -1
  209. package/lib/layout/radial/index.js.map +1 -1
  210. package/lib/registy/index.js +1 -1
  211. package/lib/registy/index.js.map +1 -1
  212. package/lib/util/index.js +5 -1
  213. package/lib/util/index.js.map +1 -1
  214. package/package.json +3 -2
  215. package/src/index.ts +7 -0
  216. package/src/layout/base.ts +54 -0
  217. package/src/layout/circular.ts +369 -0
  218. package/src/layout/comboCombined.ts +390 -0
  219. package/src/layout/comboForce.ts +873 -0
  220. package/src/layout/concentric.ts +289 -0
  221. package/src/layout/constants.ts +21 -0
  222. package/src/layout/dagre/graph.ts +104 -0
  223. package/src/layout/dagre/index.ts +31 -0
  224. package/src/layout/dagre/src/acyclic.ts +58 -0
  225. package/src/layout/dagre/src/add-border-segments.ts +47 -0
  226. package/src/layout/dagre/src/coordinate-system.ts +77 -0
  227. package/src/layout/dagre/src/data/list.ts +60 -0
  228. package/src/layout/dagre/src/debug.ts +30 -0
  229. package/src/layout/dagre/src/greedy-fas.ts +144 -0
  230. package/src/layout/dagre/src/layout.ts +580 -0
  231. package/src/layout/dagre/src/nesting-graph.ts +143 -0
  232. package/src/layout/dagre/src/normalize.ts +96 -0
  233. package/src/layout/dagre/src/order/add-subgraph-constraints.ts +29 -0
  234. package/src/layout/dagre/src/order/barycenter.ts +26 -0
  235. package/src/layout/dagre/src/order/build-layer-graph.ts +82 -0
  236. package/src/layout/dagre/src/order/cross-count.ts +77 -0
  237. package/src/layout/dagre/src/order/index.ts +105 -0
  238. package/src/layout/dagre/src/order/init-data-order.ts +27 -0
  239. package/src/layout/dagre/src/order/init-order.ts +56 -0
  240. package/src/layout/dagre/src/order/resolve-conflicts.ts +152 -0
  241. package/src/layout/dagre/src/order/sort-subgraph.ts +105 -0
  242. package/src/layout/dagre/src/order/sort.ts +76 -0
  243. package/src/layout/dagre/src/parent-dummy-chains.ts +102 -0
  244. package/src/layout/dagre/src/position/bk.ts +494 -0
  245. package/src/layout/dagre/src/position/index.ts +82 -0
  246. package/src/layout/dagre/src/rank/feasible-tree.ts +165 -0
  247. package/src/layout/dagre/src/rank/index.ts +54 -0
  248. package/src/layout/dagre/src/rank/network-simplex.ts +225 -0
  249. package/src/layout/dagre/src/rank/util.ts +157 -0
  250. package/src/layout/dagre/src/util.ts +308 -0
  251. package/src/layout/dagre.ts +423 -0
  252. package/src/layout/dagreCompound.ts +518 -0
  253. package/src/layout/er/core.ts +117 -0
  254. package/src/layout/er/forceGrid.ts +95 -0
  255. package/src/layout/er/grid.ts +185 -0
  256. package/src/layout/er/index.ts +68 -0
  257. package/src/layout/er/mysqlWorkbench.ts +345 -0
  258. package/src/layout/er/type.ts +39 -0
  259. package/src/layout/force/force-in-a-box.ts +400 -0
  260. package/src/layout/force/force.ts +391 -0
  261. package/src/layout/force/index.ts +1 -0
  262. package/src/layout/forceAtlas2/body.ts +115 -0
  263. package/src/layout/forceAtlas2/index.ts +556 -0
  264. package/src/layout/forceAtlas2/quad.ts +115 -0
  265. package/src/layout/forceAtlas2/quadTree.ts +107 -0
  266. package/src/layout/fruchterman.ts +361 -0
  267. package/src/layout/gForce.ts +487 -0
  268. package/src/layout/gpu/fruchterman.ts +314 -0
  269. package/src/layout/gpu/fruchtermanShader.ts +204 -0
  270. package/src/layout/gpu/gForce.ts +406 -0
  271. package/src/layout/gpu/gForceShader.ts +221 -0
  272. package/src/layout/grid.ts +391 -0
  273. package/src/layout/index.ts +45 -0
  274. package/src/layout/layout.ts +75 -0
  275. package/src/layout/mds.ts +140 -0
  276. package/src/layout/radial/index.ts +1 -0
  277. package/src/layout/radial/mds.ts +51 -0
  278. package/src/layout/radial/radial.ts +500 -0
  279. package/src/layout/radial/radialNonoverlapForce.ts +189 -0
  280. package/src/layout/random.ts +75 -0
  281. package/src/layout/types.ts +421 -0
  282. package/src/registy/index.ts +43 -0
  283. package/src/util/array.ts +1 -0
  284. package/src/util/function.ts +64 -0
  285. package/src/util/gpu.ts +254 -0
  286. package/src/util/index.ts +6 -0
  287. package/src/util/math.ts +158 -0
  288. package/src/util/number.ts +8 -0
  289. package/src/util/object.ts +28 -0
  290. package/src/util/string.ts +18 -0
  291. package/CHANGELOG.md +0 -78
  292. package/es/layout/dagre/src/graphlib.d.ts +0 -2
  293. package/es/layout/dagre/src/graphlib.js +0 -51
  294. package/es/layout/dagre/src/graphlib.js.map +0 -1
  295. package/lib/layout/dagre/src/graphlib.d.ts +0 -2
  296. package/lib/layout/dagre/src/graphlib.js +0 -56
  297. package/lib/layout/dagre/src/graphlib.js.map +0 -1
@@ -0,0 +1,391 @@
1
+ /**
2
+ * @fileOverview random layout
3
+ * @author shiwu.wyy@antfin.com
4
+ */
5
+
6
+ import { Edge, Model, PointTuple, ForceLayoutOptions } from "../types";
7
+ import * as d3Force from "d3-force";
8
+ import forceInABox from "./force-in-a-box";
9
+ import { isArray, isFunction, isNumber, isObject } from "../../util";
10
+ import { Base } from "../base";
11
+ import { LAYOUT_MESSAGE } from "../constants";
12
+
13
+ /**
14
+ * 经典力导布局 force-directed
15
+ */
16
+ export class ForceLayout extends Base {
17
+ /** 向心力作用点 */
18
+ public center: PointTuple = [0, 0];
19
+
20
+ /** 节点作用力 */
21
+ public nodeStrength: number | null = null;
22
+
23
+ /** 边的作用力, 默认为根据节点的入度出度自适应 */
24
+ public edgeStrength: number | null = null;
25
+
26
+ /** 是否防止节点相互覆盖 */
27
+ public preventOverlap: boolean = false;
28
+
29
+ /** 节点大小 / 直径,用于防止重叠时的碰撞检测 */
30
+ public nodeSize: number | number[] | ((d?: unknown) => number) | undefined;
31
+
32
+ /** 节点间距,防止节点重叠时节点之间的最小距离(两节点边缘最短距离) */
33
+ public nodeSpacing: ((d?: unknown) => number) | undefined;
34
+
35
+ /** 是否支持按类聚合 */
36
+ public clustering: boolean;
37
+
38
+ /** 聚类节点作用力 */
39
+ public clusterNodeStrength: number | null = null;
40
+
41
+ /** 聚类边作用力 */
42
+ public clusterEdgeStrength: number | null = null;
43
+
44
+ /** 聚类边长度 */
45
+ public clusterEdgeDistance: number | null = null;
46
+
47
+ /** 聚类节点大小 / 直径,直径越大,越分散 */
48
+ public clusterNodeSize: number | null = null;
49
+
50
+ /** 用于 foci 的力 */
51
+ public clusterFociStrength: number | null = null;
52
+
53
+ /** 默认边长度 */
54
+ public linkDistance: number = 50;
55
+
56
+ /** 自定义 force 方法 */
57
+ public forceSimulation: any;
58
+
59
+ /** 迭代阈值的衰减率 [0, 1],0.028 对应最大迭代数为 300 */
60
+ public alphaDecay: number = 0.028;
61
+
62
+ /** 停止迭代的阈值 */
63
+ public alphaMin: number = 0.001;
64
+
65
+ /** 当前阈值 */
66
+ public alpha: number = 0.3;
67
+
68
+ /** 防止重叠的力强度 */
69
+ public collideStrength: number = 1;
70
+
71
+ /** 是否启用web worker。前提是在web worker里执行布局,否则无效 */
72
+ public workerEnabled: boolean = false;
73
+
74
+ public tick: () => void = () => {};
75
+
76
+ /** 布局完成回调 */
77
+ public onLayoutEnd: () => void = () => {};
78
+
79
+ /** 是否正在布局 */
80
+ private ticking: boolean | undefined = undefined;
81
+
82
+ private edgeForce: any;
83
+
84
+ private clusterForce: any;
85
+
86
+ constructor(options?: ForceLayoutOptions) {
87
+ super();
88
+ if (options) {
89
+ this.updateCfg(options);
90
+ }
91
+ }
92
+
93
+ public getDefaultCfg() {
94
+ return {
95
+ center: [0, 0],
96
+ nodeStrength: null,
97
+ edgeStrength: null,
98
+ preventOverlap: false,
99
+ nodeSize: undefined,
100
+ nodeSpacing: undefined,
101
+ linkDistance: 50,
102
+ forceSimulation: null,
103
+ alphaDecay: 0.028,
104
+ alphaMin: 0.001,
105
+ alpha: 0.3,
106
+ collideStrength: 1,
107
+ clustering: false,
108
+ clusterNodeStrength: -1,
109
+ clusterEdgeStrength: 0.1,
110
+ clusterEdgeDistance: 100,
111
+ clusterFociStrength: 0.8,
112
+ clusterNodeSize: 10,
113
+ tick() {},
114
+ onLayoutEnd() {}, // 布局完成回调
115
+ // 是否启用web worker。前提是在web worker里执行布局,否则无效
116
+ workerEnabled: false
117
+ };
118
+ }
119
+
120
+ /**
121
+ * 初始化
122
+ * @param {object} data 数据
123
+ */
124
+ public init(data: Model) {
125
+ const self = this;
126
+ self.nodes = data.nodes || [];
127
+ const edges = data.edges || [];
128
+ self.edges = edges.map((edge) => {
129
+ const res: any = {};
130
+ const expectKeys = ["targetNode", "sourceNode", "startPoint", "endPoint"];
131
+ Object.keys(edge).forEach((key: keyof Edge) => {
132
+ if (!(expectKeys.indexOf(key) > -1)) {
133
+ res[key] = edge[key];
134
+ }
135
+ });
136
+ return res;
137
+ });
138
+ self.ticking = false;
139
+ }
140
+
141
+ /**
142
+ * 执行布局
143
+ */
144
+ public execute(reloadData?: boolean) {
145
+ const self = this;
146
+ const nodes = self.nodes;
147
+ const edges = self.edges;
148
+ // 如果正在布局,忽略布局请求
149
+ if (self.ticking) {
150
+ return;
151
+ }
152
+ let simulation = self.forceSimulation;
153
+ const alphaMin = self.alphaMin;
154
+ const alphaDecay = self.alphaDecay;
155
+ const alpha = self.alpha;
156
+ if (!simulation) {
157
+ try {
158
+ // 定义节点的力
159
+ const nodeForce = d3Force.forceManyBody();
160
+ if (self.nodeStrength) {
161
+ nodeForce.strength(self.nodeStrength);
162
+ }
163
+ simulation = d3Force.forceSimulation().nodes(nodes as any);
164
+
165
+ if (self.clustering) {
166
+ const clusterForce = forceInABox() as any;
167
+ clusterForce
168
+ .centerX(self.center[0])
169
+ .centerY(self.center[1])
170
+ .template("force")
171
+ .strength(self.clusterFociStrength);
172
+ if (edges) {
173
+ clusterForce.links(edges);
174
+ }
175
+ if (nodes) {
176
+ clusterForce.nodes(nodes);
177
+ }
178
+ clusterForce
179
+ .forceLinkDistance(self.clusterEdgeDistance)
180
+ .forceLinkStrength(self.clusterEdgeStrength)
181
+ .forceCharge(self.clusterNodeStrength)
182
+ .forceNodeSize(self.clusterNodeSize);
183
+
184
+ self.clusterForce = clusterForce;
185
+ simulation.force("group", clusterForce);
186
+ }
187
+ simulation
188
+ .force("center", d3Force.forceCenter(self.center[0], self.center[1]))
189
+ .force("charge", nodeForce)
190
+ .alpha(alpha)
191
+ .alphaDecay(alphaDecay)
192
+ .alphaMin(alphaMin);
193
+
194
+ if (self.preventOverlap) {
195
+ self.overlapProcess(simulation);
196
+ }
197
+ // 如果有边,定义边的力
198
+ if (edges) {
199
+ // d3 的 forceLayout 会重新生成边的数据模型,为了避免污染源数据
200
+ const edgeForce = d3Force
201
+ .forceLink()
202
+ .id((d: any) => d.id)
203
+ .links(edges);
204
+ if (self.edgeStrength) {
205
+ edgeForce.strength(self.edgeStrength);
206
+ }
207
+ if (self.linkDistance) {
208
+ edgeForce.distance(self.linkDistance);
209
+ }
210
+ self.edgeForce = edgeForce;
211
+ simulation.force("link", edgeForce);
212
+ }
213
+ if (self.workerEnabled && !isInWorker()) {
214
+ // 如果不是运行在web worker里,不用web worker布局
215
+ self.workerEnabled = false;
216
+ console.warn(
217
+ "workerEnabled option is only supported when running in web worker."
218
+ );
219
+ }
220
+ if (!self.workerEnabled) {
221
+ simulation
222
+ .on("tick", () => {
223
+ self.tick();
224
+ })
225
+ .on("end", () => {
226
+ self.ticking = false;
227
+ if (self.onLayoutEnd) self.onLayoutEnd();
228
+ });
229
+ self.ticking = true;
230
+ } else {
231
+ // worker is enabled
232
+ simulation.stop();
233
+ const totalTicks = getSimulationTicks(simulation);
234
+ for (let currentTick = 1; currentTick <= totalTicks; currentTick++) {
235
+ simulation.tick();
236
+ // currentTick starts from 1.
237
+ postMessage(
238
+ {
239
+ nodes,
240
+ currentTick,
241
+ totalTicks,
242
+ type: LAYOUT_MESSAGE.TICK
243
+ },
244
+ undefined as any
245
+ );
246
+ }
247
+ self.ticking = false;
248
+ }
249
+
250
+ self.forceSimulation = simulation;
251
+ self.ticking = true;
252
+ } catch (e) {
253
+ self.ticking = false;
254
+ console.warn(e);
255
+ }
256
+ } else {
257
+ if (reloadData) {
258
+ if (self.clustering && self.clusterForce) {
259
+ self.clusterForce.nodes(nodes);
260
+ self.clusterForce.links(edges);
261
+ }
262
+ simulation.nodes(nodes);
263
+ if (edges && self.edgeForce) self.edgeForce.links(edges);
264
+ else if (edges && !self.edgeForce) {
265
+ // d3 的 forceLayout 会重新生成边的数据模型,为了避免污染源数据
266
+ const edgeForce = d3Force
267
+ .forceLink()
268
+ .id((d: any) => d.id)
269
+ .links(edges);
270
+ if (self.edgeStrength) {
271
+ edgeForce.strength(self.edgeStrength);
272
+ }
273
+ if (self.linkDistance) {
274
+ edgeForce.distance(self.linkDistance);
275
+ }
276
+ self.edgeForce = edgeForce;
277
+ simulation.force("link", edgeForce);
278
+ }
279
+ }
280
+ if (self.preventOverlap) {
281
+ self.overlapProcess(simulation);
282
+ }
283
+ simulation.alpha(alpha).restart();
284
+ this.ticking = true;
285
+ }
286
+ }
287
+
288
+ /**
289
+ * 防止重叠
290
+ * @param {object} simulation 力模拟模型
291
+ */
292
+ public overlapProcess(simulation: any) {
293
+ const self = this;
294
+ const nodeSize = self.nodeSize;
295
+ const nodeSpacing = self.nodeSpacing;
296
+ let nodeSizeFunc: (d: any) => number;
297
+ let nodeSpacingFunc: any;
298
+ const collideStrength = self.collideStrength;
299
+
300
+ if (isNumber(nodeSpacing)) {
301
+ nodeSpacingFunc = () => nodeSpacing;
302
+ } else if (isFunction(nodeSpacing)) {
303
+ nodeSpacingFunc = nodeSpacing;
304
+ } else {
305
+ nodeSpacingFunc = () => 0;
306
+ }
307
+
308
+ if (!nodeSize) {
309
+ nodeSizeFunc = (d) => {
310
+ if (d.size) {
311
+ if (isArray(d.size)) {
312
+ const res = d.size[0] > d.size[1] ? d.size[0] : d.size[1];
313
+ return res / 2 + nodeSpacingFunc(d);
314
+ } if (isObject(d.size)) {
315
+ const res = d.size.width > d.size.height ? d.size.width : d.size.height;
316
+ return res / 2 + nodeSpacingFunc(d);
317
+ }
318
+ return d.size / 2 + nodeSpacingFunc(d);
319
+ }
320
+ return 10 + nodeSpacingFunc(d);
321
+ };
322
+ } else if (isFunction(nodeSize)) {
323
+ nodeSizeFunc = (d) => {
324
+ const size = nodeSize(d);
325
+ return size + nodeSpacingFunc(d);
326
+ };
327
+ } else if (isArray(nodeSize)) {
328
+ const larger = nodeSize[0] > nodeSize[1] ? nodeSize[0] : nodeSize[1];
329
+ const radius = larger / 2;
330
+ nodeSizeFunc = (d) => radius + nodeSpacingFunc(d);
331
+ } else if (isNumber(nodeSize)) {
332
+ const radius = nodeSize / 2;
333
+ nodeSizeFunc = (d) => radius + nodeSpacingFunc(d);
334
+ } else {
335
+ nodeSizeFunc = () => 10;
336
+ }
337
+
338
+ // forceCollide's parameter is a radius
339
+ simulation.force(
340
+ "collisionForce",
341
+ d3Force.forceCollide(nodeSizeFunc).strength(collideStrength)
342
+ );
343
+ }
344
+
345
+ /**
346
+ * 更新布局配置,但不执行布局
347
+ * @param {object} cfg 需要更新的配置项
348
+ */
349
+ public updateCfg(cfg: ForceLayoutOptions) {
350
+ const self = this;
351
+ if (self.ticking) {
352
+ self.forceSimulation.stop();
353
+ self.ticking = false;
354
+ }
355
+ self.forceSimulation = null;
356
+ Object.assign(self, cfg);
357
+ }
358
+
359
+ public destroy() {
360
+ const self = this;
361
+ if (self.ticking) {
362
+ self.forceSimulation.stop();
363
+ self.ticking = false;
364
+ }
365
+ self.nodes = null;
366
+ self.edges = null;
367
+ self.destroyed = true;
368
+ }
369
+ }
370
+
371
+ // Return total ticks of d3-force simulation
372
+ function getSimulationTicks(simulation: any): number {
373
+ const alphaMin = simulation.alphaMin();
374
+ const alphaTarget = simulation.alphaTarget();
375
+ const alpha = simulation.alpha();
376
+ const totalTicksFloat =
377
+ Math.log((alphaMin - alphaTarget) / (alpha - alphaTarget)) /
378
+ Math.log(1 - simulation.alphaDecay());
379
+ const totalTicks = Math.ceil(totalTicksFloat);
380
+ return totalTicks;
381
+ }
382
+ declare const WorkerGlobalScope: any;
383
+
384
+ // 判断是否运行在web worker里
385
+ function isInWorker(): boolean {
386
+ // eslint-disable-next-line no-undef
387
+ return (
388
+ typeof WorkerGlobalScope !== "undefined" &&
389
+ self instanceof WorkerGlobalScope
390
+ );
391
+ }
@@ -0,0 +1 @@
1
+ export * from './force';
@@ -0,0 +1,115 @@
1
+ import Quad from './quad';
2
+
3
+ /**
4
+ * @fileOverview body
5
+ * @author shiwu.wyy@antfin.com
6
+ */
7
+
8
+ type BodyProps = {
9
+ id?: Number;
10
+ rx: number;
11
+ ry: number;
12
+ fx?: number;
13
+ fy?: number;
14
+ mass: number;
15
+ degree: number;
16
+ g?: number;
17
+ };
18
+
19
+ // represents a body(a point mass) and its position
20
+ export default class Body {
21
+ public id: Number;
22
+ public rx: number;
23
+ public ry: number;
24
+ public fx: number;
25
+ public fy: number;
26
+ public mass: number;
27
+ public degree: number;
28
+ public g: number;
29
+
30
+ constructor(params: BodyProps) {
31
+ /**
32
+ * the id of this body, the same with the node id
33
+ * @type {number}
34
+ */
35
+ this.id = params.id || 0;
36
+ /**
37
+ * the position of this body
38
+ * @type {number}
39
+ */
40
+ this.rx = params.rx;
41
+ /**
42
+ * the position of this body
43
+ * @type {number}
44
+ */
45
+ this.ry = params.ry;
46
+ /**
47
+ * the force acting on this body
48
+ * @type {number}
49
+ */
50
+ this.fx = 0;
51
+ /**
52
+ * the force acting on this body
53
+ * @type {number}
54
+ */
55
+ this.fy = 0;
56
+ /**
57
+ * the mass of this body, =1 for a node
58
+ * @type {number}
59
+ */
60
+ this.mass = params.mass;
61
+ /**
62
+ * the degree of the node represented by this body
63
+ * @type {number}
64
+ */
65
+ this.degree = params.degree;
66
+ /**
67
+ * the parameter for repulsive force, = kr
68
+ * @type {number}
69
+ */
70
+ this.g = params.g || 0;
71
+ }
72
+ // returns the euclidean distance
73
+ distanceTo(bo: Body) {
74
+ const dx = this.rx - bo.rx;
75
+ const dy = this.ry - bo.ry;
76
+ return Math.hypot(dx, dy);
77
+ }
78
+ setPos(x: number, y: number) {
79
+ this.rx = x;
80
+ this.ry = y;
81
+ }
82
+ // resets the forces
83
+ resetForce() {
84
+ this.fx = 0;
85
+ this.fy = 0;
86
+ }
87
+ addForce(b: Body) {
88
+ const dx = b.rx - this.rx;
89
+ const dy = b.ry - this.ry;
90
+ let dist = Math.hypot(dx, dy);
91
+ dist = dist < 0.0001 ? 0.0001 : dist;
92
+ // the repulsive defined by force atlas 2
93
+ const F = (this.g * (this.degree + 1) * (b.degree + 1)) / dist;
94
+ this.fx += F * dx / dist;
95
+ this.fy += F * dy / dist;
96
+ }
97
+ // if quad contains this body
98
+ in(quad: Quad) {
99
+ return quad.contains(this.rx, this.ry);
100
+ }
101
+ // returns a new body
102
+ add(bo: Body) {
103
+ const nenwMass = this.mass + bo.mass;
104
+ const x = (this.rx * this.mass + bo.rx * bo.mass) / nenwMass;
105
+ const y = (this.ry * this.mass + bo.ry * bo.mass) / nenwMass;
106
+ const dg = this.degree + bo.degree;
107
+ const params: BodyProps = {
108
+ rx: x,
109
+ ry: y,
110
+ mass: nenwMass,
111
+ degree: dg
112
+ };
113
+ return new Body(params);
114
+ }
115
+ }