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): nodelink data supported #2967

Merged
merged 4 commits into from
Nov 12, 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
38 changes: 38 additions & 0 deletions __tests__/unit/plots/sankey/node-link-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Sankey } from '../../../../src';
import { createDiv } from '../../../utils/dom';

describe('sankey', () => {
it('dataType = nodeLink', () => {
const ALIPAY_DATA = {
nodes: [
{ id: 'A', name: 'A' },
{ id: 'B', name: 'B' },
{ id: 'C', name: 'C' },
{ id: 'D', name: 'D' },
{ id: 'E', name: 'E' },
{ id: 'F', name: 'F', fixedValue: 10 },
],
links: [
{ source: 0, target: 1, value: 160 },
{ source: 1, target: 2, value: 10 },
{ source: 2, target: 3, value: 8 },
{ source: 4, target: 3, value: 27 },
],
};

const sankey = new Sankey(createDiv(), {
height: 500,
dataType: 'node-link',
data: ALIPAY_DATA,
});

sankey.render();

const elements = sankey.chart.views[1].geometries[0].elements;

// F 元素会现实出来
expect(elements.some((el) => el.getData().name === 'F')).toBe(true);

sankey.destroy();
});
});
6 changes: 3 additions & 3 deletions src/plots/funnel/adaptor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isFunction } from '@antv/util';
import { isFunction, clone } from '@antv/util';
import { Params } from '../../core/adaptor';
import { interaction, animation, theme, scale, annotation, tooltip } from '../../adaptor/common';
import { getLocale } from '../../core/locale';
Expand Down Expand Up @@ -27,7 +27,7 @@ import { FUNNEL_CONVERSATION, FUNNEL_PERCENT } from './constant';
*/
function defaultOptions(params: Params<FunnelOptions>): Params<FunnelOptions> {
const { options } = params;
const { compareField, xField, yField, locale, funnelStyle } = options;
const { compareField, xField, yField, locale, funnelStyle, data } = options;
const i18n = getLocale(locale);

const defaultOption = {
Expand Down Expand Up @@ -70,7 +70,7 @@ function defaultOptions(params: Params<FunnelOptions>): Params<FunnelOptions> {
};
}

return deepAssign({ options: defaultOption }, params, { options: { funnelStyle: style } });
return deepAssign({ options: defaultOption }, params, { options: { funnelStyle: style, data: clone(data) } });
}

/**
Expand Down
35 changes: 26 additions & 9 deletions src/plots/sankey/helper.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { isRealNumber, pick } from '../../utils';
import { transformDataToNodeLinkData } from '../../utils/data';
import { sankeyLayout } from './layout';
import { Data } from '../../types';
import { sankeyLayout, SankeyLayoutInputData } from './layout';
import { cutoffCircle } from './circle';
import { SankeyOptions } from './types';

/**
* 是否是 node-link 类型的数据结构
* @param dataTyp
* @returns
*/
function isNodeLink(dataType: string) {
return dataType === 'node-link';
}

export function getNodeWidthRatio(nodeWidth: number, nodeWidthRatio: number, width: number) {
return isRealNumber(nodeWidth) ? nodeWidth / width : nodeWidthRatio;
}
Expand All @@ -20,6 +30,7 @@ export function getNodePaddingRatio(nodePadding: number, nodePaddingRatio: numbe
*/
export function transformToViewsData(options: SankeyOptions, width: number, height: number) {
const {
dataType,
data,
sourceField,
targetField,
Expand All @@ -34,13 +45,19 @@ export function transformToViewsData(options: SankeyOptions, width: number, heig
rawFields = [],
} = options;

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

if (!isNodeLink(dataType)) {
sankeyLayoutInputData = transformDataToNodeLinkData(
cutoffCircle(data as Data, sourceField, targetField),
sourceField,
targetField,
weightField,
rawFields
);
} else {
sankeyLayoutInputData = data;
}

// 3. layout 之后的数据
const { nodes, links } = sankeyLayout(
Expand All @@ -51,7 +68,7 @@ export function transformToViewsData(options: SankeyOptions, width: number, heig
nodeSort,
nodeDepth,
},
sankeyLayoutInputData
sankeyLayoutInputData as SankeyLayoutInputData
);

// 4. 生成绘图数据
Expand Down
60 changes: 52 additions & 8 deletions src/plots/sankey/types.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,72 @@
import { Data, Options, State, StyleAttr } from '../../types';
import { NodeDepth, NodeSort } from './layout';

/**
* node-link 数据类型的结构
*/
export type NodeLinkData = {
/**
* 节点数据
*/
readonly nodes: {
/**
* id 唯一即可,一般可以直接等于 name
*/
readonly id: string;
/**
* 节点的名称,用于 UI 上的现实
*/
readonly name: string;
/**
* 节点的值,不传则节点大小有来源求和决定
*/
readonly fixedValue?: number;
visiky marked this conversation as resolved.
Show resolved Hide resolved
}[];
/**
*
*/
readonly links: {
/**
* 来源节点在 nodes 中的 index
*/
readonly source: number;
/**
* 目标节点在 nodes 中的 index
*/
readonly target: number;
/**
* 边的值
*/
readonly value: number;
}[];
};

/** 配置类型定义 */
export interface SankeyOptions extends Omit<Options, 'xField' | 'yField' | 'xAxis' | 'yAxis'> {
export interface SankeyOptions extends Omit<Options, 'data' | 'xField' | 'yField' | 'xAxis' | 'yAxis'> {
/**
* 数据集的类型,默认为 detail
*/
readonly dataType?: 'node-link' | 'detail';
/**
* 来源字段
* 来源字段,dataType = 'node-link' 的时候,不用传
*/
readonly sourceField: string;
readonly sourceField?: string;
/**
* 去向字段
* 去向字段,dataType = 'node-link' 的时候,不用传
*/
readonly targetField: string;
readonly targetField?: string;
/**
* 权重字段
* 权重字段,dataType = 'node-link' 的时候,不用传
*/
readonly weightField: string;
readonly weightField?: string;
/**
* 附加的 元字段
*/
readonly rawFields?: string[];
/**
* 数据
*/
readonly data: Data;
readonly data: Data | NodeLinkData;
/**
* 节点宽度的比如,参考画布的宽度,默认值为 0.008
*/
Expand Down