Skip to content

Commit 94672bc

Browse files
authored
Merge pull request #247 from VisActor/feat/export-sankey-computeHierarchicNodeLinks
feat: export function computeHierarchicNodeLinks for sankey
2 parents cedf8e5 + 7b58fca commit 94672bc

File tree

3 files changed

+77
-55
lines changed

3 files changed

+77
-55
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "feat: export function computeHierarchicNodeLinks for sankey\n\n",
5+
"type": "none",
6+
"packageName": "@visactor/vlayouts"
7+
}
8+
],
9+
"packageName": "@visactor/vlayouts",
10+
"email": "[email protected]"
11+
}

packages/vlayouts/src/sankey/hierarchy.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isNil, toValidNumber } from '@visactor/vutils';
1+
import { isNil, pickWithout, toValidNumber } from '@visactor/vutils';
22

33
import type { HierarchyNodeDatum, SankeyLinkDatum, SankeyLinkElement, SankeyNodeElement } from './interface';
44

@@ -71,3 +71,65 @@ export function makeHierarchicNodes(
7171
doSubTree(originalNodes, 0, null);
7272
return nodes;
7373
}
74+
75+
export function computeHierarchicNodeLinks(
76+
originalNodes: HierarchyNodeDatum[],
77+
nodeKeyFunc: (node: HierarchyNodeDatum) => string
78+
) {
79+
const nodes: SankeyNodeElement[] = [];
80+
const links: SankeyLinkElement[] = [];
81+
const nodeMap: Record<string | number, SankeyNodeElement> = {};
82+
const linkMap: Record<string | number, SankeyLinkElement> = {};
83+
const originalLinks: (SankeyLinkDatum & { parents?: SankeyNodeElement[] })[] = [];
84+
85+
makeHierarchicNodes(originalNodes, nodeKeyFunc, nodes, nodeMap, originalLinks);
86+
87+
originalLinks.forEach((link, index) => {
88+
const key = `${link.source}-${link.target}`;
89+
const linkDatum = pickWithout(link, ['parents']);
90+
91+
(linkDatum as any).parents = link.parents.map(node => {
92+
return pickWithout(node, ['sourceLinks', 'targetLinks']);
93+
});
94+
95+
if (linkMap[key]) {
96+
linkMap[key].value += toValidNumber(link.value);
97+
98+
(linkMap[key].datum as SankeyLinkDatum[]).push(linkDatum as SankeyLinkDatum);
99+
100+
return;
101+
}
102+
const linkElement = {
103+
index,
104+
key: `${link.source}-${link.target}`,
105+
source: link.source,
106+
target: link.target,
107+
datum: [linkDatum] as any,
108+
value: link.value,
109+
parents: link.parents.map(parent => parent.key)
110+
};
111+
112+
links.push(linkElement);
113+
nodeMap[link.source].sourceLinks.push(linkElement);
114+
nodeMap[link.target].targetLinks.push(linkElement);
115+
linkMap[key] = linkElement;
116+
});
117+
118+
return { nodes, links, nodeMap };
119+
}
120+
121+
export function computeNodeValues(nodes: SankeyNodeElement[]) {
122+
for (let i = 0, len = nodes.length; i < len; i++) {
123+
const node = nodes[i];
124+
125+
node.value = Math.max(
126+
isNil(node.value) ? 0 : toValidNumber(node.value),
127+
node.sourceLinks.reduce((sum, link: SankeyLinkElement) => {
128+
return sum + (toValidNumber(link.value) ?? 0);
129+
}, 0),
130+
node.targetLinks.reduce((sum, link: SankeyLinkElement) => {
131+
return sum + (toValidNumber(link.value) ?? 0);
132+
}, 0)
133+
);
134+
}
135+
}

packages/vlayouts/src/sankey/layout.ts

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
pickWithout,
1313
toValidNumber
1414
} from '@visactor/vutils';
15-
import { makeHierarchicNodes } from './hierarchy';
15+
import { computeHierarchicNodeLinks, computeNodeValues, makeHierarchicNodes } from './hierarchy';
1616
import type {
1717
SankeyData,
1818
SankeyOptions,
@@ -243,46 +243,7 @@ export class SankeyLayout {
243243
}
244244

245245
computeHierarchicNodeLinks(originalNodes: HierarchyNodeDatum[]) {
246-
const nodes: SankeyNodeElement[] = [];
247-
const links: SankeyLinkElement[] = [];
248-
const nodeMap: Record<string | number, SankeyNodeElement> = {};
249-
const linkMap: Record<string | number, SankeyLinkElement> = {};
250-
const originalLinks: (SankeyLinkDatum & { parents?: SankeyNodeElement[] })[] = [];
251-
252-
makeHierarchicNodes(originalNodes, this._getNodeKey, nodes, nodeMap, originalLinks);
253-
254-
originalLinks.forEach((link, index) => {
255-
const key = `${link.source}-${link.target}`;
256-
const linkDatum = pickWithout(link, ['parents']);
257-
258-
(linkDatum as any).parents = link.parents.map(node => {
259-
return pickWithout(node, ['sourceLinks', 'targetLinks']);
260-
});
261-
262-
if (linkMap[key]) {
263-
linkMap[key].value += toValidNumber(link.value);
264-
265-
(linkMap[key].datum as SankeyLinkDatum[]).push(linkDatum as SankeyLinkDatum);
266-
267-
return;
268-
}
269-
const linkElement = {
270-
index,
271-
key: `${link.source}-${link.target}`,
272-
source: link.source,
273-
target: link.target,
274-
datum: [linkDatum] as any,
275-
value: link.value,
276-
parents: link.parents.map(parent => parent.key)
277-
};
278-
279-
links.push(linkElement);
280-
nodeMap[link.source].sourceLinks.push(linkElement);
281-
nodeMap[link.target].targetLinks.push(linkElement);
282-
linkMap[key] = linkElement;
283-
});
284-
285-
return { nodes, links, nodeMap };
246+
return computeHierarchicNodeLinks(originalNodes, this._getNodeKey);
286247
}
287248

288249
computeSourceTargetNodeLinks(data: { nodes?: SankeyNodeDatum[]; links: SankeyLinkDatum[] }) {
@@ -413,19 +374,7 @@ export class SankeyLayout {
413374
}
414375

415376
computeNodeValues(nodes: SankeyNodeElement[]) {
416-
for (let i = 0, len = nodes.length; i < len; i++) {
417-
const node = nodes[i];
418-
419-
node.value = Math.max(
420-
isNil(node.value) ? 0 : toValidNumber(node.value),
421-
node.sourceLinks.reduce((sum, link: SankeyLinkElement) => {
422-
return sum + (toValidNumber(link.value) ?? 0);
423-
}, 0),
424-
node.targetLinks.reduce((sum, link: SankeyLinkElement) => {
425-
return sum + (toValidNumber(link.value) ?? 0);
426-
}, 0)
427-
);
428-
}
377+
return computeNodeValues(nodes);
429378
}
430379

431380
computeNodeDepths(nodes: SankeyNodeElement[]) {

0 commit comments

Comments
 (0)