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(v2/column): support grouped and stacked column #1333

Merged
merged 1 commit into from
Jul 26, 2020
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
93 changes: 93 additions & 0 deletions __tests__/data/sales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,96 @@ export const salesByArea = [
{ area: '西北', sales: 815039.5959999998 },
{ area: '西南', sales: 1303124.508000002 },
];

export const subSalesByArea = [
{
area: '东北',
series: '消费者',
sales: 1323985.6069999991,
},
{
area: '东北',
series: '小型企业',
sales: 522739.0349999995,
},
{
area: '东北',
series: '公司',
sales: 834842.827,
},
{
area: '中南',
series: '消费者',
sales: 2057936.7620000008,
},
{
area: '中南',
series: '小型企业',
sales: 743813.0069999992,
},
{
area: '中南',
series: '公司',
sales: 1335665.3239999984,
},
{
area: '华东',
series: '消费者',
sales: 2287358.261999998,
},
{
area: '华东',
series: '小型企业',
sales: 942432.3720000006,
},
{
area: '华东',
series: '公司',
sales: 1454715.807999998,
},
{
area: '华北',
series: '消费者',
sales: 1220430.5610000012,
},
{
area: '华北',
series: '小型企业',
sales: 422100.9870000001,
},
{
area: '华北',
series: '公司',
sales: 804769.4689999995,
},
{
area: '西北',
series: '消费者',
sales: 458058.1039999998,
},
{
area: '西北',
series: '小型企业',
sales: 103523.308,
},
{
area: '西北',
series: '公司',
sales: 253458.1840000001,
},
{
area: '西南',
series: '消费者',
sales: 677302.8919999995,
},
{
area: '西南',
series: '小型企业',
sales: 156479.9319999999,
},
{
area: '西南',
series: '公司',
sales: 469341.684,
},
];
49 changes: 45 additions & 4 deletions __tests__/unit/plots/column/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Column } from '../../../../src';
import { salesByArea } from '../../../data/sales';
import { salesByArea, subSalesByArea } from '../../../data/sales';
import { createDiv } from '../../../utils/dom';

describe('column', () => {
it('x*y', () => {
const column = new Column(createDiv(), {
const column = new Column(createDiv('x*y'), {
width: 400,
height: 300,
data: salesByArea,
Expand All @@ -28,7 +28,7 @@ describe('column', () => {
});

it('x*y*color', () => {
const column = new Column(createDiv(), {
const column = new Column(createDiv('x*y*color'), {
width: 400,
height: 300,
data: salesByArea,
Expand All @@ -48,7 +48,7 @@ describe('column', () => {

it('x*y*color with color', () => {
const palette = ['red', 'yellow', 'green'];
const column = new Column(createDiv(), {
const column = new Column(createDiv('x*y*color with color'), {
width: 400,
height: 300,
data: salesByArea,
Expand All @@ -71,4 +71,45 @@ describe('column', () => {
expect(color).toBe(palette[index % palette.length]);
});
});

it('grouped column', () => {
const column = new Column(createDiv('grouped column'), {
width: 400,
height: 300,
data: subSalesByArea,
xField: 'area',
yField: 'sales',
colorField: 'series',
});

column.render();

const geometry = column.chart.geometries[0];
expect(geometry.getAdjust('dodge')).toMatchObject({
xField: 'area',
yField: 'sales',
});
expect(geometry.getAdjust('stack')).toBeUndefined();
});

it('stacked column', () => {
const column = new Column(createDiv('stacked column'), {
width: 400,
height: 300,
data: subSalesByArea,
xField: 'area',
yField: 'sales',
colorField: 'series',
isStack: true,
Copy link
Member

@hustcc hustcc Jul 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit 默认是 group,可以设置为 stack 是吧?

});

column.render();

const geometry = column.chart.geometries[0];
expect(geometry.getAdjust('dodge')).toBeUndefined();
expect(geometry.getAdjust('stack')).toMatchObject({
xField: 'area',
yField: 'sales',
});
});
});
119 changes: 112 additions & 7 deletions __tests__/unit/plots/column/label-spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Column } from '../../../../src';
import { salesByArea } from '../../../data/sales';
import { salesByArea, subSalesByArea } from '../../../data/sales';
import { createDiv } from '../../../utils/dom';

describe('column label', () => {
it('position: top', () => {
const column = new Column(createDiv(), {
it('position top', () => {
const column = new Column(createDiv('position top'), {
width: 400,
height: 300,
data: salesByArea,
Expand Down Expand Up @@ -36,8 +36,8 @@ describe('column label', () => {
});
});

it('label position middle', () => {
const column = new Column(createDiv(), {
it('position middle', () => {
const column = new Column(createDiv('position middle'), {
width: 400,
height: 300,
data: salesByArea,
Expand All @@ -62,8 +62,8 @@ describe('column label', () => {
expect(geometry.labelOption.cfg).toEqual({ position: 'middle' });
});

it('label position bottom', () => {
const column = new Column(createDiv(), {
it('position bottom', () => {
const column = new Column(createDiv('position bottom'), {
width: 400,
height: 300,
data: salesByArea,
Expand All @@ -87,4 +87,109 @@ describe('column label', () => {
// @ts-ignore
expect(geometry.labelOption.cfg).toEqual({ position: 'bottom' });
});

it('group column position top', () => {
const column = new Column(createDiv('group column position top'), {
width: 400,
height: 300,
data: subSalesByArea,
xField: 'area',
yField: 'sales',
colorField: 'series',
meta: {
sales: {
nice: true,
formatter: (v) => `${Math.floor(v / 10000)}万`,
},
},
label: {
position: 'top',
},
});

column.render();

const geometry = column.chart.geometries[0];
const labelGroups = geometry.labelsContainer.getChildren();

// @ts-ignore
expect(geometry.labelOption.cfg).toEqual({
position: 'top',
});
expect(labelGroups).toHaveLength(subSalesByArea.length);
labelGroups.forEach((label) => {
const origin = label.get('origin')._origin;
expect(label.get('children')[0].attr('text')).toBe(`${Math.floor(origin.sales / 10000)}万`);
});
});

it('group column position middle', () => {
const column = new Column(createDiv('group column position middle'), {
width: 400,
height: 300,
data: subSalesByArea,
xField: 'area',
yField: 'sales',
colorField: 'series',
meta: {
sales: {
nice: true,
formatter: (v) => `${Math.floor(v / 10000)}万`,
},
},
label: {
position: 'middle',
},
});

column.render();

const geometry = column.chart.geometries[0];
const labelGroups = geometry.labelsContainer.getChildren();

// @ts-ignore
expect(geometry.labelOption.cfg).toEqual({
position: 'middle',
});
expect(labelGroups).toHaveLength(subSalesByArea.length);
labelGroups.forEach((label) => {
const origin = label.get('origin')._origin;
expect(label.get('children')[0].attr('text')).toBe(`${Math.floor(origin.sales / 10000)}万`);
});
});

it('group column position bottom', () => {
const column = new Column(createDiv('group column position bottom'), {
width: 400,
height: 300,
data: subSalesByArea,
xField: 'area',
yField: 'sales',
colorField: 'series',
meta: {
sales: {
nice: true,
formatter: (v) => `${Math.floor(v / 10000)}万`,
},
},
label: {
position: 'bottom',
},
});

column.render();

const geometry = column.chart.geometries[0];
const labelGroups = geometry.labelsContainer.getChildren();

// @ts-ignore
expect(geometry.labelOption.cfg).toEqual({
position: 'bottom',
});
expect(labelGroups).toHaveLength(subSalesByArea.length);
labelGroups.forEach((label) => {
const origin = label.get('origin')._origin;
expect(label.get('children')[0].attr('text')).toBe(`${Math.floor(origin.sales / 10000)}万`);
});
});
});
8 changes: 7 additions & 1 deletion __tests__/utils/dom.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
/**
* 创建一个 div 节点,并放到 container,默认放到 body 上
* @param title
* @param container
*/
export function createDiv(container: HTMLElement = document.body): HTMLElement {
export function createDiv(title: string = '', container: HTMLElement = document.body): HTMLElement {
const div = document.createElement('div');

if (title) {
const titleDiv = document.createElement('div').appendChild(document.createTextNode(title));
container.appendChild(titleDiv);
}

container.appendChild(div);

return div;
Expand Down
9 changes: 7 additions & 2 deletions src/plots/column/adaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Geometry, Chart } from '@antv/g2';
import { deepMix, isFunction } from '@antv/util';
import { Params } from '../../core/adaptor';
import { findGeometry } from '../../common/helper';
import { tooltip, interaction, animation, theme } from '../../common/adaptor';
import { flow, pick } from '../../utils';
import { ColumnOptions } from './types';
import { AXIS_META_CONFIG_KEYS } from '../../constant';
Expand All @@ -12,7 +13,7 @@ import { AXIS_META_CONFIG_KEYS } from '../../constant';
*/
function field(params: Params<ColumnOptions>): Params<ColumnOptions> {
const { chart, options } = params;
const { data, xField, yField, colorField, color } = options;
const { data, xField, yField, colorField, color, isStack } = options;

chart.data(data);
const geometry = chart.interval().position(`${xField}*${yField}`);
Expand All @@ -21,6 +22,10 @@ function field(params: Params<ColumnOptions>): Params<ColumnOptions> {
geometry.color(colorField, color);
}

if (colorField && ![xField, yField].includes(colorField)) {
geometry.adjust(isStack ? 'stack' : 'dodge');
}

return params;
}

Expand Down Expand Up @@ -129,5 +134,5 @@ function label(params: Params<ColumnOptions>): Params<ColumnOptions> {
* @param params
*/
export function adaptor(params: Params<ColumnOptions>) {
return flow(field, meta, axis, legend, style, label)(params);
return flow(field, meta, axis, legend, tooltip, theme, style, label, interaction, animation)(params);
}
10 changes: 8 additions & 2 deletions src/plots/column/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ import { ShapeStyle } from '../../types/style';

export interface ColumnOptions extends Options {
/** x 轴字段 */
readonly xField?: string;
readonly xField: string;
/** y 轴字段 */
readonly yField?: string;
readonly yField: string;
/** 颜色字段,可选 */
readonly colorField?: string;
/** 是否 堆积柱状图, 默认 分组柱状图 */
readonly isStack?: boolean;
/** 柱子宽度占比 [0-1] */
readonly marginRatio?: number;
/** 分组或堆叠内部的间距,像素值 */
readonly innerPadding?: number;
Copy link
Member

@hustcc hustcc Jul 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 这两个是 v1 已经有的能力吗?

/** 柱子样式配置,可选 */
readonly columnStyle?: ShapeStyle | ((x: any, y: any, color?: any) => ShapeStyle);
}