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(change-data): 饼图支持动态更新数据 & 其他若干处理,见 PR 描述 #2257

Merged
merged 9 commits into from
Jan 24, 2021
15 changes: 14 additions & 1 deletion __tests__/unit/core/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { deepMix, isEqual, clone } from '@antv/util';
import { Line, G2 } from '../../../src';
import { Line, G2, Plot } from '../../../src';
import { partySupport } from '../../data/party-support';
import { createDiv } from '../../utils/dom';
import { delay } from '../../utils/delay';
Expand Down Expand Up @@ -300,4 +300,17 @@ describe('core', () => {

line.destroy();
});

it('default-options', () => {
type CustomPlotOptions = {};
class CustomPlot extends Plot<CustomPlotOptions> {
type: 'custom';
getSchemaAdaptor() {
return () => {};
}
}
const plot = new CustomPlot(createDiv(), {});
// @ts-ignore
expect(Plot.getDefaultOptions()).toEqual(plot.getDefaultOptions());
});
});
54 changes: 52 additions & 2 deletions __tests__/unit/plots/pie/annotation-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ describe('annotation', () => {

it('text annotation', () => {
expect(pie.chart.getController('annotation').getComponents().length).toBe(2);
const annotation1: HTMLDivElement = pie.chart.ele.querySelector('.g2-html-annotation');
// @ts-ignore
expect(annotation1.style.fontWeight).toBe(`${Pie.getDefaultOptions().statistic.title.style.fontWeight}`);

pie.update({
...pie.options,
annotations: [
{
type: 'text',
Expand All @@ -34,7 +36,6 @@ describe('annotation', () => {

it('text annotation and line annotation', () => {
pie.update({
...pie.options,
statistic: null,
annotations: [
{
Expand All @@ -54,6 +55,55 @@ describe('annotation', () => {
expect(pie.chart.getController('annotation').getComponents()[1].component.get('type')).toBe('line');
});

it('annotation with change data', () => {
pie.update({ data: [], statistic: {} });
expect(pie.chart.getController('annotation').getComponents().length).toBe(4);
expect(pie.chart.getController('annotation').getComponents()[0].component.get('content')).toBe('辅助文本');
// @ts-ignore
let annotations = pie.chart.ele.querySelectorAll('.g2-html-annotation') as HTMLDivElement[];
expect(annotations[0].innerText).toBe('总计');
expect(annotations[1].innerText).toBe('');

pie.changeData(salesByArea);
setTimeout(() => {
expect(pie.chart.getController('annotation').getComponents().length).toBe(4);
expect(pie.chart.getController('annotation').getComponents()[0].component.get('content')).toBe('辅助文本');
// @ts-ignore
annotations = pie.chart.ele.querySelectorAll('.g2-html-annotation') as HTMLDivElement[];
expect(annotations[0].innerText).toBe('总计');
expect(annotations[1].innerText).toBe(salesByArea.reduce((a, b) => a + b.sales, 0));
}, 0);
});

it('先更新为 false,再更新出现, 且样式不变', () => {
const pie1 = new Pie(createDiv(), {
width: 300,
height: 400,
data: salesByArea,
colorField: 'sales',
angleField: 'area',
innerRadius: 0.64,
});

pie1.render();
let annotation1: HTMLDivElement = pie1.chart.ele.querySelector('.g2-html-annotation');
const style = annotation1.style;

pie1.update({ statistic: { title: false, content: false } });
expect(pie1.chart.getController('annotation').getComponents().length).toBe(0);

pie1.update({ statistic: { title: {}, content: {} } });
expect(pie1.chart.getController('annotation').getComponents().length).toBe(2);
annotation1 = pie1.chart.ele.querySelector('.g2-html-annotation');
// @ts-ignore
expect(annotation1.innerText).toBe('总计');
// 样式依然是默认样式
// @ts-ignore
expect(annotation1.style).toEqual(style);

pie1.destroy();
});

afterAll(() => {
pie.destroy();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Pie } from '../../../../src';
import { createDiv } from '../../../utils/dom';
import { delay } from '../../../utils/delay';

describe('饼图 数据全空', () => {
describe('饼图 异常数据', () => {
const data = [];
for (let i = 0; i < 5; i++) {
data.push({ type: `类型 ${i}`, value: 0 });
Expand Down Expand Up @@ -99,10 +99,7 @@ describe('饼图 数据全空', () => {
expect(elements.length).toBe(0);

await delay(500);
pie.update({
...pie.options,
data,
});
pie.changeData(data);

elements = pie.chart.geometries[0].elements;
expect(every(elements, (ele) => ele.getBBox().width > 0)).toBe(true);
Expand All @@ -126,3 +123,109 @@ describe('饼图 数据全空', () => {
pie.destroy();
});
});

describe('数据存在 NaN', () => {
const createPie = (data): Pie => {
const pie = new Pie(createDiv(), {
angleField: 'value',
colorField: 'type',
data,
});

pie.render();
return pie;
};

it('初始化存在 NaN', () => {
const pie = createPie([
{ type: '1', value: NaN },
{ type: '2', value: 10 },
]);
expect(pie.chart).toBeDefined();
expect(pie.chart.getData()).toEqual([{ type: '2', value: 10 }]);

pie.destroy();
});

it('从正常数据 change 到存在 NaN', () => {
const pie = createPie([{ type: '2', value: 10 }]);
pie.changeData([{ type: '1', value: NaN }]);
expect(pie.chart).toBeDefined();
expect(pie.options.data).toEqual([{ type: '1', value: NaN }]);
expect(pie.chart.getData()).toEqual([]);
pie.destroy();
});

it('从 [] change 到存在 NaN', () => {
const pie = createPie([]);
pie.changeData([{ type: '1', value: NaN }]);
expect(pie.chart).toBeDefined();
expect(pie.options.data).toEqual([{ type: '1', value: NaN }]);
expect(pie.chart.getData()).toEqual([]);
pie.destroy();
});

it('从存在数据 0 change 到存在 NaN', () => {
const pie = createPie([
{ type: '1', value: 0 },
{ type: '1', value: 0 },
]);
expect(pie.chart.getData().length).toBe(2);
pie.changeData([{ type: '1', value: NaN }]);
expect(pie.chart).toBeDefined();
expect(pie.options.data).toEqual([{ type: '1', value: NaN }]);
expect(pie.chart.getData()).toEqual([]);

pie.changeData([
{ type: '1', value: NaN },
{ type: '2', value: 0 },
]);
expect(pie.chart.getData()[0]).toMatchObject({ type: '2', value: 0 });
expect(pie.chart.geometries[0].elements.length).toEqual(1);
pie.destroy();
});
});

describe('环图 changeData', () => {
const createDonut = (data): Pie => {
const donut = new Pie(createDiv(), {
angleField: 'value',
colorField: 'type',
data,
innerRadius: 0.6,
annotations: [{ type: 'text', content: 'xx', position: ['min', 'max'] }],
});

donut.render();
return donut;
};

it('normal', () => {
const donut = createDonut([]);
expect(donut.chart.getController('annotation').getComponents().length).toBe(3);

donut.changeData([
{ type: '1', value: 1 },
{ type: '2', value: 3 },
]);
expect(donut.chart.getController('annotation').getComponents().length).toBe(3);

donut.destroy();
});

it('从数据全 0 到正常', () => {
const donut = createDonut([
{ type: '1', value: 0 },
{ type: '2', value: 0 },
]);
expect(donut.chart.getController('annotation').getComponents().length).toBe(3);

donut.changeData([
{ type: '1', value: 1 },
{ type: '2', value: 3 },
]);
expect(donut.chart.getController('annotation').getComponents().length).toBe(3);

donut.destroy();
});
});
8 changes: 8 additions & 0 deletions __tests__/unit/plots/pie/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Pie } from '../../../../src';
import { DEFAULT_OPTIONS } from '../../../../src/plots/pie/contants';
import { POSITIVE_NEGATIVE_DATA } from '../../../data/common';
import { createDiv } from '../../../utils/dom';

Expand All @@ -19,6 +20,9 @@ describe('pie', () => {
});

pie.render();
expect(pie.type).toBe('pie');
// @ts-ignore
expect(pie.getDefaultOptions()).toBe(Pie.getDefaultOptions());

const geometry = pie.chart.geometries[0];
const elements = geometry.elements;
Expand Down Expand Up @@ -167,4 +171,8 @@ describe('pie', () => {

pie.destroy();
});

it('defaultOptions 保持从 constants 中获取', () => {
expect(Pie.getDefaultOptions()).toEqual(DEFAULT_OPTIONS);
});
});
17 changes: 17 additions & 0 deletions __tests__/unit/plots/pie/statistic-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Chart } from '@antv/g2';
import { Pie, PieOptions } from '../../../../src';
import { DEFAULT_OPTIONS } from '../../../../src/plots/pie/contants';
import { POSITIVE_NEGATIVE_DATA } from '../../../data/common';
import { delay } from '../../../utils/delay';
import { createDiv } from '../../../utils/dom';
Expand Down Expand Up @@ -301,6 +302,22 @@ describe('中心文本 - 指标卡', () => {
expect(htmlAnnotations[0].getBoundingClientRect().width).toEqual(600);
});

it('statistic 默认继承 defaultOptions', () => {
pie.update({ statistic: null });
expect(pie.chart.ele.querySelectorAll('.g2-html-annotation').length).toBe(0);

pie.update({ statistic: {} });
expect(pie.chart.ele.querySelectorAll('.g2-html-annotation').length).toBe(2);
expect(pie.options.statistic).toEqual({});
setTimeout(() => {
// @ts-ignore
const annotations = pie.chart.ele.querySelectorAll('.g2-html-annotation') as HTMLDivElement[];
expect(annotations[0].style.fontSize).toEqual(DEFAULT_OPTIONS.statistic.title.fontSize);
expect(annotations[1].style.color).toEqual(DEFAULT_OPTIONS.statistic.content.color);
expect(annotations[1].style).toMatchObject(DEFAULT_OPTIONS.statistic.content);
}, 0);
});

afterEach(() => {
pie.chart.clear();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { adaptOffset, getTotalValue } from '../../../../../src/plots/pie/utils';
import { adaptOffset, getTotalValue, isAllZero, processIllegalData } from '../../../../src/plots/pie/utils';

describe('utils of pie plot', () => {
const data = [
Expand Down Expand Up @@ -58,4 +58,28 @@ describe('utils of pie plot', () => {
expect(adaptOffset('spider', '30%')).toBe('30%');
expect(adaptOffset('spider', NaN)).toBe(NaN);
});

it('过滤非法数据', () => {
const data = [{ type: '1', value: 0 }];
expect(processIllegalData(data, 'value')).toEqual(data);
data.push({ type: '2', value: 1 });
expect(processIllegalData(data, 'value')).toEqual(data);
data.push({ type: '3', value: null });
expect(processIllegalData(data, 'value')).toEqual(data);
data.push({ type: '4', value: undefined });
expect(processIllegalData(data, 'value')).toEqual(data.slice(0, 3));
data.push({ type: '5', value: NaN });
expect(processIllegalData(data, 'value')).toEqual(data.slice(0, 3));
});

it('判断是否全 0', () => {
const data = [{ type: '1', value: 0 }];
expect(isAllZero(data, 'value')).toBe(true);
data.push({ type: '2', value: 0 });
expect(isAllZero(data, 'value')).toBe(true);
data.push({ type: '3', value: null });
expect(isAllZero(data, 'value')).toBe(false);
data.push({ type: '4', value: undefined });
expect(isAllZero(data, 'value')).toBe(false);
});
});
33 changes: 33 additions & 0 deletions examples/dynamic-plots/basic/demo/dynamic-pie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Pie } from '@antv/g2plot';

const data = [
{ type: '分类一', value: 27 },
{ type: '分类二', value: 25 },
{ type: '分类三', value: 18 },
{ type: '分类四', value: 15 },
{ type: '分类五', value: 10 },
{ type: '其他', value: 5 },
];

const piePlot = new Pie('container', {
appendPadding: 10,
data,
angleField: 'value',
colorField: 'type',
radius: 0.9,
label: {
type: 'inner',
offset: '-30%',
content: ({ percent }) => `${(percent * 100).toFixed(0)}%`,
style: {
fontSize: 14,
textAlign: 'center',
},
},
interactions: [{ type: 'element-active' }],
});

piePlot.render();
setInterval(() => {
piePlot.changeData(data.map((d) => ({ ...d, value: d.value * Math.random() })));
}, 1200);
8 changes: 8 additions & 0 deletions examples/dynamic-plots/basic/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
"en": "Gauge updating with dynamic"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_d314dd/afts/img/A*O2aDSImbWDgAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "dynamic-pie.ts",
"title": {
"zh": "动态更新的饼图",
"en": "Pie updating with dynamic"
},
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/JQXEkyg2Rm/dongtaigengxinshuju-pie-after.gif"
}
]
}
Loading