From 5badecd558a1abe9e95228a85c26e4a60991155e Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Sat, 22 May 2021 07:33:19 +0800 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20=E4=BB=A3=E7=A0=81=E6=B4=81?= =?UTF-8?q?=E7=99=96,=E4=BF=AE=E6=94=B9=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plots/column/adaptor.ts | 4 +--- src/utils/index.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plots/column/adaptor.ts b/src/plots/column/adaptor.ts index e192336984..7bead0e88f 100644 --- a/src/plots/column/adaptor.ts +++ b/src/plots/column/adaptor.ts @@ -1,5 +1,4 @@ import { Params } from '../../core/adaptor'; -import { findGeometry } from '../../utils'; import { tooltip, slider, @@ -15,9 +14,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 } from '../../utils'; import { getDataWhetherPecentage } from '../../utils/transform/percent'; -import { adjustYMetaByZero } from '../../utils/data'; import { Datum } from '../../types'; import { ColumnOptions } from './types'; diff --git a/src/utils/index.ts b/src/utils/index.ts index 5249a43269..bb358ea422 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -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'; From 54ba710c128c53ba1a234848b1bce21a2af56af4 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Sat, 22 May 2021 08:45:26 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(#2572):=20=E4=BF=AE=E5=A4=8D=E5=A0=86?= =?UTF-8?q?=E5=8F=A0=E5=88=86=E7=BB=84=E6=9F=B1=E7=8A=B6=E5=9B=BE=20toolti?= =?UTF-8?q?p=20=E5=B1=95=E7=A4=BA=E4=B8=8D=E6=AD=A3=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close: #2572 --- src/plots/column/adaptor.ts | 51 ++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/plots/column/adaptor.ts b/src/plots/column/adaptor.ts index 7bead0e88f..152995d8c6 100644 --- a/src/plots/column/adaptor.ts +++ b/src/plots/column/adaptor.ts @@ -1,6 +1,7 @@ +import { Types } from '@antv/g2'; +import { each, filter, isMatch } from '@antv/util'; import { Params } from '../../core/adaptor'; import { - tooltip, slider, interaction, animation, @@ -14,7 +15,7 @@ import { import { conversionTag } from '../../adaptor/conversion-tag'; import { connectedArea } from '../../adaptor/connected-area'; import { interval } from '../../adaptor/geometries'; -import { flow, transformLabel, deepAssign, findGeometry, adjustYMetaByZero } from '../../utils'; +import { flow, transformLabel, deepAssign, findGeometry, adjustYMetaByZero, pick } from '../../utils'; import { getDataWhetherPecentage } from '../../utils/transform/percent'; import { Datum } from '../../types'; import { ColumnOptions } from './types'; @@ -195,6 +196,50 @@ function label(params: Params): Params { return params; } +/** + * 柱形图 tooltip 配置 (对堆叠、分组做特殊处理) + * @param params + */ +function columnTooltip(params: Params): Params { + 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 @@ -210,7 +255,7 @@ export function adaptor(params: Params, isBar = false) { meta, axis, legend, - tooltip, + columnTooltip, slider, scrollbar, label, From 354bf57d6b4b8d6dbf5377c33d2b007298ae5570 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Sat, 22 May 2021 09:17:56 +0800 Subject: [PATCH 3/4] =?UTF-8?q?test(#2572):=20=E6=B7=BB=E5=8A=A0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=8D=95=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/bugs/issue-2572-spec.ts | 191 ++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 __tests__/bugs/issue-2572-spec.ts diff --git a/__tests__/bugs/issue-2572-spec.ts b/__tests__/bugs/issue-2572-spec.ts new file mode 100644 index 0000000000..41e6217b9d --- /dev/null +++ b/__tests__/bugs/issue-2572-spec.ts @@ -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) => + `
${title}
${ + items.length + }
${items.reduce((a, b) => a + b.data.order_amt, 0)}
`, + }, + }); + 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); + }); +}); From ca5c4b466311e41bb9c437bd9347b26f502c0d54 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Sat, 22 May 2021 09:26:52 +0800 Subject: [PATCH 4/4] =?UTF-8?q?docs(column):=20=E6=96=B0=E5=A2=9E=E5=A0=86?= =?UTF-8?q?=E5=8F=A0=E5=88=86=E7=BB=84=E6=9F=B1=E7=8A=B6=E5=9B=BE=E7=9A=84?= =?UTF-8?q?=20demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/column/grouped/demo/meta.json | 16 +++++++++---- .../column/grouped/demo/tooltip-formatter.ts | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 examples/column/grouped/demo/tooltip-formatter.ts diff --git a/examples/column/grouped/demo/meta.json b/examples/column/grouped/demo/meta.json index 910f52a0fe..3e37260703 100644 --- a/examples/column/grouped/demo/meta.json +++ b/examples/column/grouped/demo/meta.json @@ -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", diff --git a/examples/column/grouped/demo/tooltip-formatter.ts b/examples/column/grouped/demo/tooltip-formatter.ts new file mode 100644 index 0000000000..4caa082266 --- /dev/null +++ b/examples/column/grouped/demo/tooltip-formatter.ts @@ -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(); + });