@antv/layout 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/layout.min.js +1 -1
- package/dist/layout.min.js.map +1 -1
- package/es/layout/comboCombined.js +6 -21
- package/es/layout/comboCombined.js.map +1 -1
- package/es/layout/grid.js +2 -0
- package/es/layout/grid.js.map +1 -1
- package/es/layout/types.d.ts +7 -3
- package/lib/layout/comboCombined.js +6 -21
- package/lib/layout/comboCombined.js.map +1 -1
- package/lib/layout/grid.js +2 -0
- package/lib/layout/grid.js.map +1 -1
- package/lib/layout/types.d.ts +7 -3
- package/package.json +2 -1
- package/src/index.ts +7 -0
- package/src/layout/base.ts +54 -0
- package/src/layout/circular.ts +369 -0
- package/src/layout/comboCombined.ts +391 -0
- package/src/layout/comboForce.ts +873 -0
- package/src/layout/concentric.ts +289 -0
- package/src/layout/constants.ts +21 -0
- package/src/layout/dagre/graph.ts +104 -0
- package/src/layout/dagre/index.ts +31 -0
- package/src/layout/dagre/src/acyclic.ts +58 -0
- package/src/layout/dagre/src/add-border-segments.ts +47 -0
- package/src/layout/dagre/src/coordinate-system.ts +77 -0
- package/src/layout/dagre/src/data/list.ts +60 -0
- package/src/layout/dagre/src/debug.ts +30 -0
- package/src/layout/dagre/src/greedy-fas.ts +144 -0
- package/src/layout/dagre/src/layout.ts +580 -0
- package/src/layout/dagre/src/nesting-graph.ts +143 -0
- package/src/layout/dagre/src/normalize.ts +96 -0
- package/src/layout/dagre/src/order/add-subgraph-constraints.ts +29 -0
- package/src/layout/dagre/src/order/barycenter.ts +26 -0
- package/src/layout/dagre/src/order/build-layer-graph.ts +82 -0
- package/src/layout/dagre/src/order/cross-count.ts +77 -0
- package/src/layout/dagre/src/order/index.ts +105 -0
- package/src/layout/dagre/src/order/init-data-order.ts +27 -0
- package/src/layout/dagre/src/order/init-order.ts +56 -0
- package/src/layout/dagre/src/order/resolve-conflicts.ts +152 -0
- package/src/layout/dagre/src/order/sort-subgraph.ts +105 -0
- package/src/layout/dagre/src/order/sort.ts +76 -0
- package/src/layout/dagre/src/parent-dummy-chains.ts +102 -0
- package/src/layout/dagre/src/position/bk.ts +494 -0
- package/src/layout/dagre/src/position/index.ts +82 -0
- package/src/layout/dagre/src/rank/feasible-tree.ts +165 -0
- package/src/layout/dagre/src/rank/index.ts +54 -0
- package/src/layout/dagre/src/rank/network-simplex.ts +225 -0
- package/src/layout/dagre/src/rank/util.ts +157 -0
- package/src/layout/dagre/src/util.ts +308 -0
- package/src/layout/dagre.ts +423 -0
- package/src/layout/dagreCompound.ts +518 -0
- package/src/layout/er/core.ts +117 -0
- package/src/layout/er/forceGrid.ts +95 -0
- package/src/layout/er/grid.ts +185 -0
- package/src/layout/er/index.ts +68 -0
- package/src/layout/er/mysqlWorkbench.ts +345 -0
- package/src/layout/er/type.ts +39 -0
- package/src/layout/force/force-in-a-box.ts +400 -0
- package/src/layout/force/force.ts +391 -0
- package/src/layout/force/index.ts +1 -0
- package/src/layout/forceAtlas2/body.ts +115 -0
- package/src/layout/forceAtlas2/index.ts +556 -0
- package/src/layout/forceAtlas2/quad.ts +115 -0
- package/src/layout/forceAtlas2/quadTree.ts +107 -0
- package/src/layout/fruchterman.ts +361 -0
- package/src/layout/gForce.ts +487 -0
- package/src/layout/gpu/fruchterman.ts +314 -0
- package/src/layout/gpu/fruchtermanShader.ts +204 -0
- package/src/layout/gpu/gForce.ts +406 -0
- package/src/layout/gpu/gForceShader.ts +221 -0
- package/src/layout/grid.ts +393 -0
- package/src/layout/index.ts +45 -0
- package/src/layout/layout.ts +75 -0
- package/src/layout/mds.ts +140 -0
- package/src/layout/radial/index.ts +1 -0
- package/src/layout/radial/mds.ts +51 -0
- package/src/layout/radial/radial.ts +500 -0
- package/src/layout/radial/radialNonoverlapForce.ts +189 -0
- package/src/layout/random.ts +75 -0
- package/src/layout/types.ts +425 -0
- package/src/registy/index.ts +43 -0
- package/src/util/array.ts +1 -0
- package/src/util/function.ts +64 -0
- package/src/util/gpu.ts +254 -0
- package/src/util/index.ts +6 -0
- package/src/util/math.ts +158 -0
- package/src/util/number.ts +8 -0
- package/src/util/object.ts +28 -0
- package/src/util/string.ts +18 -0
- package/CHANGELOG.md +0 -88
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileOverview Combo force layout
|
|
3
|
+
* @author shiwu.wyy@antfin.com
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Edge,
|
|
8
|
+
Combo,
|
|
9
|
+
OutNode,
|
|
10
|
+
PointTuple,
|
|
11
|
+
ComboTree,
|
|
12
|
+
ComboCombinedLayoutOptions
|
|
13
|
+
} from "./types";
|
|
14
|
+
import { FORCE_LAYOUT_TYPE_MAP } from './constants';
|
|
15
|
+
import { Base } from "./base";
|
|
16
|
+
import { isArray, isNumber, isFunction, traverseTreeUp, isObject, findMinMaxNodeXY } from "../util";
|
|
17
|
+
import { CircularLayout, ConcentricLayout, GridLayout, RadialLayout, GForceLayout, MDSLayout } from ".";
|
|
18
|
+
|
|
19
|
+
type Node = OutNode & {
|
|
20
|
+
depth?: number;
|
|
21
|
+
itemType?: string;
|
|
22
|
+
comboId?: string;
|
|
23
|
+
fx?: number;
|
|
24
|
+
fy?: number;
|
|
25
|
+
mass?: number;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* combined two layouts (inner and outer) for graph with combos
|
|
30
|
+
*/
|
|
31
|
+
export class ComboCombinedLayout extends Base {
|
|
32
|
+
|
|
33
|
+
/** 布局中心 */
|
|
34
|
+
public center: PointTuple = [0, 0];
|
|
35
|
+
|
|
36
|
+
/** 内部计算参数 */
|
|
37
|
+
public nodes: Node[] = [];
|
|
38
|
+
|
|
39
|
+
public edges: Edge[] = [];
|
|
40
|
+
|
|
41
|
+
public combos: Combo[] = [];
|
|
42
|
+
|
|
43
|
+
public comboEdges: Edge[] = [];
|
|
44
|
+
|
|
45
|
+
/** 节点大小,用于防止节点之间的重叠 */
|
|
46
|
+
public nodeSize: number | number[] | ((d?: unknown) => number) | undefined;
|
|
47
|
+
|
|
48
|
+
/** 节点/combo最小间距,防止重叠时的间隙 */
|
|
49
|
+
public spacing: ((d?: unknown) => number) | number | undefined;
|
|
50
|
+
|
|
51
|
+
/** 最外层的布局算法,需要使用同步的布局算法,默认为 forceAtlas2 */
|
|
52
|
+
public outerLayout: any;
|
|
53
|
+
|
|
54
|
+
/** combo 内部的布局算法,默认为 concentric */
|
|
55
|
+
public innerLayout: ConcentricLayout | CircularLayout | GridLayout | RadialLayout;
|
|
56
|
+
|
|
57
|
+
/** Combo 内部的 padding */
|
|
58
|
+
public comboPadding:
|
|
59
|
+
| ((d?: unknown) => number)
|
|
60
|
+
| number
|
|
61
|
+
| number[]
|
|
62
|
+
| undefined = 10;
|
|
63
|
+
|
|
64
|
+
public comboTrees: ComboTree[] = [];
|
|
65
|
+
|
|
66
|
+
constructor(options?: ComboCombinedLayoutOptions) {
|
|
67
|
+
super();
|
|
68
|
+
this.updateCfg(options);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public getDefaultCfg() {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 执行布局
|
|
77
|
+
*/
|
|
78
|
+
public execute() {
|
|
79
|
+
const self = this;
|
|
80
|
+
const nodes = self.nodes;
|
|
81
|
+
const center = self.center;
|
|
82
|
+
|
|
83
|
+
if (!nodes || nodes.length === 0) {
|
|
84
|
+
if (self.onLayoutEnd) self.onLayoutEnd();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (nodes.length === 1) {
|
|
88
|
+
nodes[0].x = center[0];
|
|
89
|
+
nodes[0].y = center[1];
|
|
90
|
+
if (self.onLayoutEnd) self.onLayoutEnd();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
self.initVals();
|
|
95
|
+
|
|
96
|
+
// layout
|
|
97
|
+
self.run();
|
|
98
|
+
if (self.onLayoutEnd) self.onLayoutEnd();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public run() {
|
|
102
|
+
const self = this;
|
|
103
|
+
const { nodes, edges, combos, comboEdges, center } = self;
|
|
104
|
+
|
|
105
|
+
const nodeMap: any = {};
|
|
106
|
+
nodes.forEach((node) => {
|
|
107
|
+
nodeMap[node.id] = node;
|
|
108
|
+
});
|
|
109
|
+
const comboMap: any = {};
|
|
110
|
+
combos.forEach((combo) => {
|
|
111
|
+
comboMap[combo.id] = combo;
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const innerGraphs: any = self.getInnerGraphs(nodeMap);
|
|
115
|
+
|
|
116
|
+
// 每个 innerGraph 作为一个节点,带有大小,参与 force 计算
|
|
117
|
+
const outerNodeIds: string[] = [];
|
|
118
|
+
const outerNodes: Node[] = [];
|
|
119
|
+
const nodeAncestorIdMap: { [key: string]: string } = {};
|
|
120
|
+
let allHaveNoPosition = true;
|
|
121
|
+
this.comboTrees.forEach((cTree) => {
|
|
122
|
+
const innerNode = innerGraphs[cTree.id];
|
|
123
|
+
// 代表 combo 的节点
|
|
124
|
+
const oNode: Node = {
|
|
125
|
+
...cTree,
|
|
126
|
+
x: innerNode.x || comboMap[cTree.id].x,
|
|
127
|
+
y: innerNode.y || comboMap[cTree.id].y,
|
|
128
|
+
fx: innerNode.fx || comboMap[cTree.id].fx,
|
|
129
|
+
fy: innerNode.fy || comboMap[cTree.id].fy,
|
|
130
|
+
mass: innerNode.mass || comboMap[cTree.id].mass,
|
|
131
|
+
size: innerNode.size
|
|
132
|
+
};
|
|
133
|
+
outerNodes.push(oNode);
|
|
134
|
+
if (!isNaN(oNode.x) && oNode.x !== 0 && !isNaN(oNode.y) && oNode.y !== 0) {
|
|
135
|
+
allHaveNoPosition = false;
|
|
136
|
+
} else {
|
|
137
|
+
oNode.x = Math.random() * 100;
|
|
138
|
+
oNode.y = Math.random() * 100;
|
|
139
|
+
}
|
|
140
|
+
outerNodeIds.push(cTree.id);
|
|
141
|
+
traverseTreeUp<ComboTree>(cTree, (child) => {
|
|
142
|
+
if (child.id !== cTree.id) nodeAncestorIdMap[child.id] = cTree.id;
|
|
143
|
+
return true;
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
nodes.forEach((node) => {
|
|
147
|
+
if (node.comboId && comboMap[node.comboId]) return;
|
|
148
|
+
// 代表节点的节点
|
|
149
|
+
const oNode: Node = { ...node };
|
|
150
|
+
outerNodes.push(oNode);
|
|
151
|
+
if (!isNaN(oNode.x) && oNode.x !== 0 && !isNaN(oNode.y) && oNode.y !== 0) {
|
|
152
|
+
allHaveNoPosition = false;
|
|
153
|
+
} else {
|
|
154
|
+
oNode.x = Math.random() * 100;
|
|
155
|
+
oNode.y = Math.random() * 100;
|
|
156
|
+
}
|
|
157
|
+
outerNodeIds.push(node.id);
|
|
158
|
+
});
|
|
159
|
+
const outerEdges: any = [];
|
|
160
|
+
edges.concat(comboEdges).forEach((edge) => {
|
|
161
|
+
const sourceAncestorId = nodeAncestorIdMap[edge.source] || edge.source;
|
|
162
|
+
const targetAncestorId = nodeAncestorIdMap[edge.target] || edge.target;
|
|
163
|
+
// 若两个点的祖先都在力导图的节点中,且是不同的节点,创建一条链接两个祖先的边到力导图的边中
|
|
164
|
+
if (sourceAncestorId !== targetAncestorId &&
|
|
165
|
+
outerNodeIds.includes(sourceAncestorId) &&
|
|
166
|
+
outerNodeIds.includes(targetAncestorId)) {
|
|
167
|
+
outerEdges.push({
|
|
168
|
+
source: sourceAncestorId,
|
|
169
|
+
target: targetAncestorId
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// 若有需要最外层的 combo 或节点,则对最外层执行力导向
|
|
175
|
+
if (outerNodes?.length) {
|
|
176
|
+
if (outerNodes.length === 1) {
|
|
177
|
+
outerNodes[0].x = center[0];
|
|
178
|
+
outerNodes[0].y = center[1];
|
|
179
|
+
} else {
|
|
180
|
+
const outerData = {
|
|
181
|
+
nodes: outerNodes,
|
|
182
|
+
edges: outerEdges
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// 需要使用一个同步的布局
|
|
186
|
+
// @ts-ignore
|
|
187
|
+
const outerLayout = this.outerLayout || new GForceLayout({
|
|
188
|
+
gravity: 1,
|
|
189
|
+
factor: 2,
|
|
190
|
+
linkDistance: (edge: any, source: any, target: any) => {
|
|
191
|
+
const nodeSize = ((source.size?.[0] || 30) + (target.size?.[0] || 30)) / 2;
|
|
192
|
+
return Math.min(nodeSize * 1.5, 700);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
const outerLayoutType = outerLayout.getType?.();
|
|
196
|
+
outerLayout.updateCfg({
|
|
197
|
+
center,
|
|
198
|
+
kg: 5,
|
|
199
|
+
preventOverlap: true,
|
|
200
|
+
animate: false,
|
|
201
|
+
});
|
|
202
|
+
// 若所有 outerNodes 都没有位置,且 outerLayout 是力导家族的布局,则先执行 preset mds 或 grid
|
|
203
|
+
if (allHaveNoPosition && FORCE_LAYOUT_TYPE_MAP[outerLayoutType]) {
|
|
204
|
+
const outerLayoutPreset = outerNodes.length < 100 ? new MDSLayout() : new GridLayout();
|
|
205
|
+
outerLayoutPreset.layout(outerData);
|
|
206
|
+
}
|
|
207
|
+
outerLayout.layout(outerData);
|
|
208
|
+
}
|
|
209
|
+
// 根据外部布局结果,平移 innerGraphs 中的节点(第一层)
|
|
210
|
+
outerNodes.forEach((oNode) => {
|
|
211
|
+
const innerGraph = innerGraphs[oNode.id];
|
|
212
|
+
if (!innerGraph) {
|
|
213
|
+
const node = nodeMap[oNode.id];
|
|
214
|
+
if (node) {
|
|
215
|
+
node.x = oNode.x;
|
|
216
|
+
node.y = oNode.y;
|
|
217
|
+
}
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
innerGraph.visited = true;
|
|
221
|
+
innerGraph.x = oNode.x;
|
|
222
|
+
innerGraph.y = oNode.y;
|
|
223
|
+
innerGraph.nodes.forEach((node: OutNode) => {
|
|
224
|
+
node.x += oNode.x;
|
|
225
|
+
node.y += oNode.y;
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 至上而下遍历树处理下面各层节点位置
|
|
231
|
+
const innerGraphIds = Object.keys(innerGraphs);
|
|
232
|
+
for (let i = innerGraphIds.length - 1; i >= 0; i--) {
|
|
233
|
+
const id = innerGraphIds[i];
|
|
234
|
+
const innerGraph = innerGraphs[id];
|
|
235
|
+
if (!innerGraph) continue;
|
|
236
|
+
innerGraph.nodes.forEach((node: OutNode) => {
|
|
237
|
+
if (!innerGraph.visited) {
|
|
238
|
+
node.x += (innerGraph.x || 0);
|
|
239
|
+
node.y += (innerGraph.y || 0);
|
|
240
|
+
}
|
|
241
|
+
if (nodeMap[node.id]) {
|
|
242
|
+
nodeMap[node.id].x = node.x;
|
|
243
|
+
nodeMap[node.id].y = node.y;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
if (comboMap[id]) {
|
|
247
|
+
comboMap[id].x = innerGraph.x;
|
|
248
|
+
comboMap[id].y = innerGraph.y;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { nodes, edges, combos, comboEdges };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private getInnerGraphs(nodeMap: any) {
|
|
255
|
+
const self = this;
|
|
256
|
+
const { comboTrees, nodeSize, edges, comboPadding, spacing } = self;
|
|
257
|
+
const innerGraphs: any = {};
|
|
258
|
+
|
|
259
|
+
// @ts-ignore
|
|
260
|
+
const innerGraphLayout: any = this.innerLayout || (new ConcentricLayout({ sortBy: 'id' }));
|
|
261
|
+
innerGraphLayout.center = [0, 0];
|
|
262
|
+
innerGraphLayout.preventOverlap = true;
|
|
263
|
+
innerGraphLayout.nodeSpacing = spacing;
|
|
264
|
+
|
|
265
|
+
(comboTrees || []).forEach((ctree: any) => {
|
|
266
|
+
traverseTreeUp<ComboTree>(ctree, (treeNode) => {
|
|
267
|
+
// @ts-ignore
|
|
268
|
+
let padding = comboPadding?.(treeNode) || 10; // 返回的最大值
|
|
269
|
+
if (isArray(padding)) padding = Math.max(...padding);
|
|
270
|
+
if (!treeNode.children?.length) {
|
|
271
|
+
// 空 combo
|
|
272
|
+
if (treeNode.itemType === 'combo') {
|
|
273
|
+
const treeNodeSize = padding ? [padding * 2, padding * 2] : [30, 30];
|
|
274
|
+
innerGraphs[treeNode.id] = {
|
|
275
|
+
id: treeNode.id,
|
|
276
|
+
nodes: [],
|
|
277
|
+
size: treeNodeSize
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
// 非空 combo
|
|
282
|
+
const innerGraphNodes = treeNode.children.map((child) => {
|
|
283
|
+
if (child.itemType === 'combo') return innerGraphs[child.id];
|
|
284
|
+
const oriNode = nodeMap[child.id] || {};
|
|
285
|
+
return { ...oriNode, ...child };
|
|
286
|
+
});
|
|
287
|
+
const innerGraphNodeIds = innerGraphNodes.map((node) => node.id);
|
|
288
|
+
const innerGraphData = {
|
|
289
|
+
nodes: innerGraphNodes,
|
|
290
|
+
edges: edges.filter((edge) => innerGraphNodeIds.includes(edge.source) && innerGraphNodeIds.includes(edge.target))
|
|
291
|
+
};
|
|
292
|
+
let minNodeSize = Infinity;
|
|
293
|
+
innerGraphNodes.forEach((node) => {
|
|
294
|
+
// @ts-ignore
|
|
295
|
+
if (!node.size) node.size = innerGraphs[node.id]?.size || nodeSize?.(node) || [30, 30];
|
|
296
|
+
if (isNumber(node.size)) node.size = [node.size, node.size];
|
|
297
|
+
if (minNodeSize > node.size[0]) minNodeSize = node.size[0];
|
|
298
|
+
if (minNodeSize > node.size[1]) minNodeSize = node.size[1];
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// 根据节点数量、spacing,调整布局参数
|
|
302
|
+
|
|
303
|
+
innerGraphLayout.layout(innerGraphData);
|
|
304
|
+
const { minX, minY, maxX, maxY } = findMinMaxNodeXY(innerGraphNodes);
|
|
305
|
+
const innerGraphSize = Math.max(maxX - minX, maxY - minY, minNodeSize) + padding * 2;
|
|
306
|
+
innerGraphs[treeNode.id] = {
|
|
307
|
+
id: treeNode.id,
|
|
308
|
+
nodes: innerGraphNodes,
|
|
309
|
+
size: [innerGraphSize, innerGraphSize]
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
return true;
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
return innerGraphs;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
private initVals() {
|
|
319
|
+
const self = this;
|
|
320
|
+
|
|
321
|
+
const nodeSize = self.nodeSize;
|
|
322
|
+
const spacing = self.spacing;
|
|
323
|
+
let nodeSizeFunc: (d: any) => number;
|
|
324
|
+
let spacingFunc: (d: any) => number;
|
|
325
|
+
|
|
326
|
+
// nodeSpacing to function
|
|
327
|
+
if (isNumber(spacing)) {
|
|
328
|
+
spacingFunc = () => spacing as any;
|
|
329
|
+
} else if (isFunction(spacing)) {
|
|
330
|
+
spacingFunc = spacing;
|
|
331
|
+
} else {
|
|
332
|
+
spacingFunc = () => 0;
|
|
333
|
+
}
|
|
334
|
+
this.spacing = spacingFunc;
|
|
335
|
+
|
|
336
|
+
// nodeSize to function
|
|
337
|
+
if (!nodeSize) {
|
|
338
|
+
nodeSizeFunc = (d) => {
|
|
339
|
+
const spacing = spacingFunc(d);
|
|
340
|
+
if (d.size) {
|
|
341
|
+
if (isArray(d.size)) {
|
|
342
|
+
const res = d.size[0] > d.size[1] ? d.size[0] : d.size[1];
|
|
343
|
+
return (res + spacing) / 2;
|
|
344
|
+
} if (isObject(d.size)) {
|
|
345
|
+
const res = d.size.width > d.size.height ? d.size.width : d.size.height;
|
|
346
|
+
return (res + spacing) / 2;
|
|
347
|
+
}
|
|
348
|
+
return (d.size + spacing) / 2;
|
|
349
|
+
}
|
|
350
|
+
return 10 + spacing / 2;
|
|
351
|
+
};
|
|
352
|
+
} else if (isFunction(nodeSize)) {
|
|
353
|
+
nodeSizeFunc = (d) => {
|
|
354
|
+
const size = nodeSize(d);
|
|
355
|
+
const spacing = spacingFunc(d);
|
|
356
|
+
if (isArray(d.size)) {
|
|
357
|
+
const res = d.size[0] > d.size[1] ? d.size[0] : d.size[1];
|
|
358
|
+
return (res + spacing) / 2;
|
|
359
|
+
}
|
|
360
|
+
return ((size || 10) + spacing) / 2;
|
|
361
|
+
};
|
|
362
|
+
} else if (isArray(nodeSize)) {
|
|
363
|
+
const larger = nodeSize[0] > nodeSize[1] ? nodeSize[0] : nodeSize[1];
|
|
364
|
+
const radius = larger / 2;
|
|
365
|
+
nodeSizeFunc = (d) => radius + spacingFunc(d) / 2;
|
|
366
|
+
} else {
|
|
367
|
+
// number type
|
|
368
|
+
const radius = nodeSize / 2;
|
|
369
|
+
nodeSizeFunc = (d) => radius + spacingFunc(d) / 2;
|
|
370
|
+
}
|
|
371
|
+
this.nodeSize = nodeSizeFunc;
|
|
372
|
+
|
|
373
|
+
// comboPadding to function
|
|
374
|
+
const comboPadding = self.comboPadding;
|
|
375
|
+
let comboPaddingFunc: (d: any) => number;
|
|
376
|
+
if (isNumber(comboPadding)) {
|
|
377
|
+
comboPaddingFunc = () => comboPadding as any;
|
|
378
|
+
} else if (isArray(comboPadding)) {
|
|
379
|
+
comboPaddingFunc = () => Math.max.apply(null, comboPadding);
|
|
380
|
+
} else if (isFunction(comboPadding)) {
|
|
381
|
+
comboPaddingFunc = comboPadding;
|
|
382
|
+
} else {
|
|
383
|
+
// null type
|
|
384
|
+
comboPaddingFunc = () => 0;
|
|
385
|
+
}
|
|
386
|
+
this.comboPadding = comboPaddingFunc;
|
|
387
|
+
}
|
|
388
|
+
public getType() {
|
|
389
|
+
return "comboCombined";
|
|
390
|
+
}
|
|
391
|
+
}
|