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

fix(#2572): 修复堆叠分组状图 tooltip 展示不正常 (只展示第一个小分组的数据) #2576

Merged
merged 4 commits into from
May 24, 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
191 changes: 191 additions & 0 deletions __tests__/bugs/issue-2572-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import { Column } from '../../src';
import { createDiv, removeDom } from '../utils/dom';

describe('#2572', () => {
const data = [
{
product_type: '办公用品',
sex: '男',
order_amt: 8,
product_sub_type: '橡皮擦',
},
{
product_type: '办公用品',
sex: '男',
order_amt: 10,
product_sub_type: '书架',
},
{
product_type: '办公用品',
sex: '男',
order_amt: 20,
product_sub_type: '砚台',
},
{
product_type: '办公用品',
sex: '女',
order_amt: 13,
product_sub_type: '砚台',
},
{
product_type: '办公用品',
sex: '女',
order_amt: 21,
product_sub_type: '橡皮擦',
},
{
product_type: '办公用品',
sex: '女',
order_amt: 21,
product_sub_type: '书架',
},
{
product_type: '家电家具',
sex: '男',
order_amt: 13,
product_sub_type: '洗衣机',
},
{
product_type: '家电家具',
sex: '女',
order_amt: 2,
product_sub_type: '洗衣机',
},
{
product_type: '家电家具',
sex: '男',
order_amt: 5,
product_sub_type: '微波炉',
},
{
product_type: '家电家具',
sex: '男',
order_amt: 14,
product_sub_type: '电磁炉',
},
{
product_type: '家电家具',
sex: '女',
order_amt: 23,
product_sub_type: '微波炉',
},
{
product_type: '家电家具',
sex: '女',
order_amt: 23,
product_sub_type: '电磁炉',
},
{
product_type: '电子产品',
sex: '男',
order_amt: 33,
product_sub_type: '电脑',
},
{
product_type: '电子产品',
sex: '女',
order_amt: 4,
product_sub_type: '电脑',
},
{
product_type: '电子产品',
sex: '女',
order_amt: 23,
product_sub_type: 'switch',
},
{
product_type: '电子产品',
sex: '男',
order_amt: 20.9,
product_sub_type: 'switch',
},
{
product_type: '电子产品',
sex: '男',
order_amt: 5.9,
product_sub_type: '鼠标',
},
{
product_type: '电子产品',
sex: '女',
order_amt: 5.9,
product_sub_type: '鼠标',
},
];
const div = createDiv();
const plot = new Column(div, {
data,
xField: 'product_type',
yField: 'order_amt',
isGroup: true,
isStack: true,
seriesField: 'product_sub_type',
groupField: 'sex',
});

plot.render();
const box = plot.chart.geometries[0].elements[0].getBBox();
const point = { x: box.x + box.width / 2, y: box.y + box.height / 2 };

expect(plot.chart.getController('tooltip').getTooltipItems(point).length).toBe(3);

it('堆叠分组柱状图 tooltip 展示不正常', () => {
plot.chart.showTooltip(point);

expect(div.querySelectorAll('.g2-tooltip-list-item').length).toBe(3 * 2 /** 分组:男 + 女 */);
expect((div.querySelector('.g2-tooltip-name') as HTMLElement).innerText).toBe(
`${data[0].product_sub_type} - ${data[0].sex}`
);
expect((div.querySelector('.g2-tooltip-value') as HTMLElement).innerText).toBe(`${data[0].order_amt}`);
plot.chart.hideTooltip();
});

it('堆叠分组柱状图 tooltip 更新 formatter', () => {
plot.update({
tooltip: {
formatter: (datum) => ({ name: 'xx', value: 100 }),
},
});
plot.chart.showTooltip(point);

expect((div.querySelector('.g2-tooltip-name') as HTMLElement).innerText).toBe('xx');
expect((div.querySelector('.g2-tooltip-value') as HTMLElement).innerText).toBe('100');
plot.chart.hideTooltip();

plot.update({
tooltip: {
formatter: (datum) => ({ name: datum.sex, value: 100 }),
},
});

plot.chart.showTooltip(point);

expect((div.querySelectorAll('.g2-tooltip-name')[1] as HTMLElement).innerText).toBe('女');
expect((div.querySelectorAll('.g2-tooltip-value')[1] as HTMLElement).innerText).toBe('100');
plot.chart.hideTooltip();
});

it('堆叠分组柱状图 tooltip 更新 customContent', () => {
plot.update({
tooltip: {
customContent: (title, items) =>
`<div><div class="tooltip-title">${title}</div><div class="tooltip-name">${
items.length
}</div><div class="tooltip-value">${items.reduce((a, b) => a + b.data.order_amt, 0)}</div></div>`,
},
});
plot.chart.showTooltip(point);

expect((div.querySelector('.tooltip-title') as HTMLElement).innerText).toBe(data[0].product_type);
expect((div.querySelector('.tooltip-name') as HTMLElement).innerText).toBe('6');
expect((div.querySelector('.tooltip-value') as HTMLElement).innerText).toBe(
`${data.filter((d) => d.product_type === '办公用品').reduce((a, b) => a + b.order_amt, 0)}`
);
plot.chart.hideTooltip();
});

afterAll(() => {
plot.destroy();
removeDom(div);
});
});
16 changes: 12 additions & 4 deletions examples/column/grouped/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,28 @@
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/vA%26pfMx397/0d8d9a6e-51ba-48f2-bc6d-091d77d94e2e.png"
},
{
"filename": "stacked2.ts",
"filename": "stacked.ts",
"title": {
"zh": "堆叠分组柱状图",
"en": "Stacked grouped column plot"
},
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/mp10Ax%24Mvx/4c6f19b4-2549-4023-8756-bce61bf6c50e.png"
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/9ExrwrpVrA/908eff62-1132-4dbb-8c3c-9cbe8183c6d8.png"
},
{
"filename": "stacked.ts",
"filename": "tooltip-formatter.ts",
"title": {
"zh": "对 Tooltip 进行 formatter",
"en": "Formatter for tooltip"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_d314dd/afts/img/A*zDnZQLk2L5wAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "stacked2.ts",
"title": {
"zh": "堆叠分组柱状图",
"en": "Stacked grouped column plot"
},
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/9ExrwrpVrA/908eff62-1132-4dbb-8c3c-9cbe8183c6d8.png"
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/mp10Ax%24Mvx/4c6f19b4-2549-4023-8756-bce61bf6c50e.png"
},
{
"filename": "dodge-padding.ts",
Expand Down
23 changes: 23 additions & 0 deletions examples/column/grouped/demo/tooltip-formatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Column } from '@antv/g2plot';

fetch('https://gw.alipayobjects.com/os/antfincdn/mor%26R5yBI9/stack-group-column.json')
.then((data) => data.json())
.then((data) => {
const column = new Column('container', {
data,
xField: 'product_type',
yField: 'order_amt',
isGroup: true,
isStack: true,
seriesField: 'product_sub_type',
groupField: 'sex',
tooltip: {
formatter: (datum) => ({
name: `${datum.product_sub_type} ${datum.sex === '男' ? '👦' : '👧'}`,
value: datum.order_amt,
}),
},
});

column.render();
});
53 changes: 48 additions & 5 deletions src/plots/column/adaptor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Types } from '@antv/g2';
import { each, filter, isMatch } from '@antv/util';
import { Params } from '../../core/adaptor';
import { findGeometry } from '../../utils';
import {
tooltip,
slider,
interaction,
animation,
Expand All @@ -15,9 +15,8 @@ import {
import { conversionTag } from '../../adaptor/conversion-tag';
import { connectedArea } from '../../adaptor/connected-area';
import { interval } from '../../adaptor/geometries';
import { flow, transformLabel, deepAssign } from '../../utils';
import { flow, transformLabel, deepAssign, findGeometry, adjustYMetaByZero, pick } from '../../utils';
import { getDataWhetherPecentage } from '../../utils/transform/percent';
import { adjustYMetaByZero } from '../../utils/data';
import { Datum } from '../../types';
import { ColumnOptions } from './types';

Expand Down Expand Up @@ -197,6 +196,50 @@ function label(params: Params<ColumnOptions>): Params<ColumnOptions> {
return params;
}

/**
* 柱形图 tooltip 配置 (对堆叠、分组做特殊处理)
* @param params
*/
function columnTooltip(params: Params<ColumnOptions>): Params<ColumnOptions> {
const { chart, options } = params;
const { tooltip, isGroup, isStack, groupField, data, xField, yField, seriesField } = options;

if (tooltip === false) {
chart.tooltip(false);
} else {
let tooltipOptions = tooltip;
// fix: https://github.com/antvis/G2Plot/issues/2572
if (isGroup && isStack) {
const tooltipFormatter =
tooltipOptions?.formatter ||
((datum: Datum) => ({ name: `${datum[seriesField]} - ${datum[groupField]}`, value: datum[yField] }));
tooltipOptions = {
...tooltipOptions,
customItems: (originalItems: Types.TooltipItem[]) => {
const items: Types.TooltipItem[] = [];
each(originalItems, (item: Types.TooltipItem) => {
// Find datas in same cluster
const datas = filter(data, (d) => isMatch(d, pick(item.data, [xField, seriesField])));
datas.forEach((datum) => {
items.push({
...item,
value: datum[yField],
data: datum,
mappingData: { _origin: datum },
...tooltipFormatter(datum),
});
});
});
return items;
},
};
}
chart.tooltip(tooltipOptions);
}

return params;
}

/**
* 柱形图适配器
* @param params
Expand All @@ -212,7 +255,7 @@ export function adaptor(params: Params<ColumnOptions>, isBar = false) {
meta,
axis,
legend,
tooltip,
columnTooltip,
slider,
scrollbar,
label,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export { kebabCase } from './kebab-case';
export { renderStatistic, renderGaugeStatistic } from './statistic';
export { measureTextWidth } from './measure-text';
export { isBetween, isRealNumber } from './number';
export { processIllegalData } from './data';
export * from './data';
visiky marked this conversation as resolved.
Show resolved Hide resolved