Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sankey): 桑基图支持配置 rawFields, 在节点和边上获取更多原始数据信息 #2533

Merged
merged 2 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions __tests__/data/parallel-set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
export const PARALLEL_SET = [
{
Survived: 'Perished',
Sex: 'Male',
Age: 'Adult',
Class: 'Crew',
value: 670,
},
{
Survived: 'Perished',
Sex: 'Male',
Age: 'Adult',
Class: 'Third Class',
value: 387,
},
{
Survived: 'Perished',
Sex: 'Male',
Age: 'Adult',
Class: 'Second Class',
value: 154,
},
{
Survived: 'Perished',
Sex: 'Male',
Age: 'Adult',
Class: 'First Class',
value: 118,
},
{
Survived: 'Perished',
Sex: 'Male',
Age: 'Child',
Class: 'Third Class',
value: 35,
},
{
Survived: 'Perished',
Sex: 'Female',
Age: 'Adult',
Class: 'Crew',
value: 3,
},
{
Survived: 'Perished',
Sex: 'Female',
Age: 'Adult',
Class: 'Third Class',
value: 89,
},
{
Survived: 'Perished',
Sex: 'Female',
Age: 'Adult',
Class: 'Second Class',
value: 13,
},
{
Survived: 'Perished',
Sex: 'Female',
Age: 'Adult',
Class: 'First Class',
value: 4,
},
{
Survived: 'Perished',
Sex: 'Female',
Age: 'Child',
Class: 'Third Class',
value: 17,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Adult',
Class: 'Crew',
value: 192,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Adult',
Class: 'Third Class',
value: 75,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Adult',
Class: 'Second Class',
value: 14,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Adult',
Class: 'First Class',
value: 57,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Child',
Class: 'Third Class',
value: 13,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Child',
Class: 'Second Class',
value: 11,
},
{
Survived: 'Survived',
Sex: 'Male',
Age: 'Child',
Class: 'First Class',
value: 5,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Adult',
Class: 'Crew',
value: 20,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Adult',
Class: 'Third Class',
value: 76,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Adult',
Class: 'Second Class',
value: 80,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Adult',
Class: 'First Class',
value: 140,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Child',
Class: 'Third Class',
value: 14,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Child',
Class: 'Second Class',
value: 13,
},
{
Survived: 'Survived',
Sex: 'Female',
Age: 'Child',
Class: 'First Class',
value: 1,
},
];
45 changes: 44 additions & 1 deletion __tests__/unit/plots/sankey/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Datum, Sankey } from '../../../../src';
import { createDiv } from '../../../utils/dom';
import { createDiv, removeDom } from '../../../utils/dom';
import { ENERGY_RELATIONS } from '../../../data/sankey-energy';
import { PARALLEL_SET } from '../../../data/parallel-set';

describe('sankey', () => {
it('sankey', () => {
Expand Down Expand Up @@ -161,4 +162,46 @@ describe('sankey', () => {

sankey.destroy();
});

it('sankey rawFields', () => {
const data = [];
const keys = ['Survived', 'Sex', 'Age', 'Class'];
PARALLEL_SET.forEach((d) => {
keys.reduce((a, b) => {
if (a && b) {
data.push({
source: d[a],
target: d[b],
value: d.value,
path: `${d[keys[0]]} -> ${d[keys[1]]} -> ${d[keys[2]]} -> ${d[keys[3]]}`,
});
}
return b;
});
});

const dom = createDiv();
const sankey = new Sankey(dom, {
data: data,
sourceField: 'source',
targetField: 'target',
weightField: 'value',
nodeWidthRatio: 0.01,
nodePaddingRatio: 0.03,
nodeDraggable: true,
});

sankey.render();
expect(sankey.chart.views[0].getData()[0].path).not.toBeDefined();
expect(sankey.chart.views[1].getData()[0].path).not.toBeDefined();

sankey.update({ rawFields: ['path'] });
expect(sankey.chart.views[0].getData()[0].path).toBeDefined();
expect(sankey.chart.views[1].getData()[0].path).toBeDefined();
expect(sankey.chart.views[0].getData()[0].path).toBe('Perished -> Male -> Adult -> Crew');
expect(sankey.chart.views[1].getData()[0].path).toBe('Perished -> Male -> Adult -> Crew');

sankey.destroy();
removeDom(dom);
});
});
8 changes: 8 additions & 0 deletions docs/api/plots/sankey.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ Sets the target node data field of Sankey diagram. For the above data, for examp

Set the weight field information of the relationship between nodes. The larger the data, the larger the edge. For example, for the above data, it is: 'value'.

#### rawFields

<description>**optional** _string[_</description>

Raw fields of original data. With the 'rawsFields' definition, you can get the original (raw) datum on node or edge elements.

<playground path="relation-plots/sankey/demo/draggable.ts" rid="sankey-raw-fields"></playground>

### Geometry Style

#### nodeStyle
Expand Down
8 changes: 8 additions & 0 deletions docs/api/plots/sankey.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ order: 27

设置节点之间关系的权重字段信息,数据越大,边越大。比如针对上述数据,就是: `value`。

#### rawFields

<description>**optional** _string[_</description>

其他原始字段,便于在节点、边定义 tooltip 或者 label 时取用。

<playground path="relation-plots/sankey/demo/draggable.ts" rid="sankey-raw-fields"></playground>

### Geometry Style

#### nodeStyle
Expand Down
48 changes: 48 additions & 0 deletions examples/relation-plots/sankey/demo/draggable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* @file Parallel sets are like parallel coordinates, but for categorical dimensions.
*
* Parallel Sets: Visual Analysis of Categorical Data. See more in https://kosara.net/publications/Bendix-InfoVis-2005.html
*/
import { Sankey } from '@antv/g2plot';

fetch('https://gw.alipayobjects.com/os/antfincdn/nokcOpy6fF/draggable-sankey.json')
.then((data) => data.json())
.then((data) => {
const sankeyData = [];
const keys = ['Survived', 'Sex', 'Age', 'Class'];
data.forEach((d) => {
keys.reduce((a, b) => {
if (a && b) {
sankeyData.push({
source: d[a],
target: d[b],
value: d.value,
path: `${d[keys[0]]} -> ${d[keys[1]]} -> ${d[keys[2]]} -> ${d[keys[3]]}`,
});
}
return b;
});
});

const sankey = new Sankey('container', {
data: sankeyData,
sourceField: 'source',
targetField: 'target',
weightField: 'value',
nodeWidthRatio: 0.01,
nodePaddingRatio: 0.03,
nodeDraggable: true,
rawFields: ['path'],
tooltip: {
fields: ['path', 'value'],
formatter: ({ path, value }) => {
return {
name: path,
value: value,
};
},
},
});

sankey.render();
});
8 changes: 8 additions & 0 deletions examples/relation-plots/sankey/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
"en": "Energy sankey"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_d314dd/afts/img/A*W-V0QYiLLbgAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "draggable.ts",
"title": {
"zh": "可拖拽节点桑基图",
"en": "Draggable sankey"
},
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/n1taFikWlA/aedefca9-04ba-4588-97ec-82903c039224.png"
}
]
}
14 changes: 6 additions & 8 deletions src/plots/sankey/helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isRealNumber } from '../../utils/number';
import { isRealNumber, pick } from '../../utils';
import { transformDataToNodeLinkData } from '../../utils/data';
import { sankeyLayout } from './layout';
import { cutoffCircle } from './circle';
Expand Down Expand Up @@ -31,13 +31,15 @@ export function transformToViewsData(options: SankeyOptions, width: number, heig
nodeWidth,
nodeWidthRatio,
nodeDepth,
rawFields = [],
} = options;

const sankeyLayoutInputData = transformDataToNodeLinkData(
cutoffCircle(data, sourceField, targetField),
sourceField,
targetField,
weightField
weightField,
rawFields
);

// 3. layout 之后的数据
Expand All @@ -56,9 +58,7 @@ export function transformToViewsData(options: SankeyOptions, width: number, heig
return {
nodes: nodes.map((node) => {
return {
x: node.x,
y: node.y,
name: node.name,
...pick(node, ['x', 'y', 'name', ...rawFields]),
isNode: true,
};
}),
Expand All @@ -67,9 +67,7 @@ export function transformToViewsData(options: SankeyOptions, width: number, heig
source: link.source.name,
target: link.target.name,
name: link.source.name || link.target.name,
x: link.x,
y: link.y,
value: link.value,
...pick(link, ['x', 'y', 'value', ...rawFields]),
isNode: false,
};
}),
Expand Down
4 changes: 4 additions & 0 deletions src/plots/sankey/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export interface SankeyOptions extends Omit<Options, 'xField' | 'yField' | 'xAxi
* 权重字段
*/
readonly weightField: string;
/**
* 附加的 元字段
*/
readonly rawFields?: string[];
/**
* 数据
*/
Expand Down
Loading