Skip to content

Commit 40cbc62

Browse files
authored
feat(v2/pie): 饼图数据全为 0 的处理 (#1335)
* feat(v2/pie): 饼图全 0 处理,调整position映射,不影响label和legend映射angleField * feat(v2/pie): 增加 tooltip 显示单测 * refactor(v2/pie): 修改 cr 建议
1 parent f9e1e5c commit 40cbc62

File tree

2 files changed

+131
-3
lines changed

2 files changed

+131
-3
lines changed
+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { IGroup } from '@antv/g2/lib/dependents';
2+
import { every } from '@antv/util';
3+
import { Pie } from '../../../../src';
4+
import { createDiv } from '../../../utils/dom';
5+
import { delay } from '../../../utils/delay';
6+
7+
describe('饼图 数据全空', () => {
8+
const data = [];
9+
for (let i = 0; i < 5; i++) {
10+
data.push({ type: `类型 ${i}`, value: 0 });
11+
}
12+
13+
it('数据全部为 0', () => {
14+
const div = createDiv();
15+
div.id = '#1';
16+
const pie = new Pie(div, {
17+
width: 400,
18+
height: 400,
19+
data,
20+
angleField: 'value',
21+
colorField: 'type',
22+
label: {
23+
callback: (value) => {
24+
return {
25+
content: value,
26+
};
27+
},
28+
},
29+
tooltip: {},
30+
});
31+
32+
pie.render();
33+
34+
const elements = pie.chart.geometries[0].elements;
35+
expect(elements.length).toBe(5);
36+
expect(every(elements, (ele) => ele.getBBox().width > 0)).toBe(true);
37+
const labels = pie.chart.geometries[0].labelsContainer.getChildren();
38+
expect(every(labels, (label) => (label as IGroup).getChildren()[0].attr('text') === 0)).toBe(true);
39+
});
40+
41+
it('数据全部为 0, 设置 angleField meta', async () => {
42+
const pie = new Pie(createDiv(), {
43+
width: 400,
44+
height: 400,
45+
data,
46+
angleField: 'value',
47+
colorField: 'type',
48+
meta: {
49+
value: {
50+
formatter: (v) => `${v} 个`,
51+
},
52+
},
53+
label: {},
54+
tooltip: {},
55+
});
56+
57+
pie.render();
58+
59+
const elements = pie.chart.geometries[0].elements;
60+
expect(elements.length).toBe(5);
61+
// @ts-ignore
62+
expect(every(elements, (ele) => ele.getBBox().width > 0)).toBe(true);
63+
const labels = pie.chart.geometries[0].labelsContainer.getChildren();
64+
expect(every(labels, (label) => (label as IGroup).getChildren()[0].attr('text') === '0 个')).toBe(true);
65+
66+
const positionFields = pie.chart.geometries[0].getAttribute('position').getFields();
67+
const point = pie.chart.getXY({ 1: data[0].type, [positionFields[1]]: 1 / data.length });
68+
const tooltipItems = pie.chart.getTooltipItems(point);
69+
expect(tooltipItems[1].value).toBe('0 个');
70+
});
71+
72+
it('数据为 [], 延迟 3s 加载数据全为 0, 延迟 3s 加载数据正常', async () => {
73+
const pie = new Pie(createDiv(), {
74+
width: 400,
75+
height: 400,
76+
data: [],
77+
angleField: 'value',
78+
colorField: 'type',
79+
label: {
80+
callback: (value) => {
81+
return {
82+
content: value,
83+
};
84+
},
85+
},
86+
tooltip: {},
87+
});
88+
pie.render();
89+
90+
let elements = pie.chart.geometries[0].elements;
91+
expect(elements.length).toBe(0);
92+
93+
await delay(500);
94+
pie.update({
95+
...pie.options,
96+
data,
97+
});
98+
99+
elements = pie.chart.geometries[0].elements;
100+
expect(every(elements, (ele) => ele.getBBox().width > 0)).toBe(true);
101+
expect(elements.length).toBe(data.length);
102+
103+
await delay(300);
104+
pie.update({
105+
...pie.options,
106+
data: [{ type: '类型1', value: 1 }],
107+
meta: {},
108+
});
109+
110+
elements = pie.chart.geometries[0].elements;
111+
expect(elements.length).toBe(1);
112+
const labels = pie.chart.geometries[0].labelsContainer.getChildren();
113+
expect(every(labels, (label) => (label as IGroup).getChildren()[0].attr('text') === 1)).toBe(true);
114+
const point = pie.chart.getXY({ 1: '类型 1', value: 1 });
115+
const tooltipItems = pie.chart.getTooltipItems(point);
116+
expect(tooltipItems[0].value).toBe('1');
117+
});
118+
});

src/plots/pie/adaptor.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { deepMix, each, get, isFunction } from '@antv/util';
1+
import { deepMix, each, every, get, isFunction } from '@antv/util';
22
import { Params } from '../../core/adaptor';
33
import { tooltip, interaction, animation, theme } from '../../common/adaptor';
44
import { flow } from '../../utils';
@@ -14,8 +14,18 @@ function field(params: Params<PieOptions>): Params<PieOptions> {
1414
const { chart, options } = params;
1515
const { data, angleField, colorField, color } = options;
1616

17-
chart.data(data);
18-
const geometry = chart.interval().position(`1*${angleField}`).adjust({ type: 'stack' });
17+
const geometry = chart.interval();
18+
19+
const allZero = every(data, (d) => d[angleField] === 0);
20+
if (allZero) {
21+
// 数据全 0 处理,调整 position 映射
22+
const percentageField = '$$percentage$$';
23+
chart.data(data.map((d) => ({ ...d, [percentageField]: 1 / data.length })));
24+
geometry.position(`1*${percentageField}`).adjust({ type: 'stack' }).tooltip(`${colorField}*${angleField}`);
25+
} else {
26+
chart.data(data);
27+
geometry.position(`1*${angleField}`).adjust({ type: 'stack' });
28+
}
1929

2030
if (colorField) {
2131
geometry.color(colorField, color);

0 commit comments

Comments
 (0)