Skip to content

Commit b1d8f47

Browse files
authored
refactor(bar): 条形图重构,不需要反转数据 调整下坐标系即可 (#2914)
* refactor(bar): 条形图重构,不需要反转数据 调整下坐标系即可 需要 G2 层支持对 scrollbar 反转 * feat(bar): 条形图数据不进行反转 & 修改单测 * fix(conversion-bar): 修复转化率组件在 vertical 方向的位置问题 & 单测 * test: 修复条形图单测
1 parent 69087ae commit b1d8f47

File tree

13 files changed

+141
-76
lines changed

13 files changed

+141
-76
lines changed

__tests__/bugs/bar-changedata-spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ describe('bar changeData should keep order', () => {
3030
barPlot.changeData(data);
3131

3232
// 绘制从下至上
33-
expect(barPlot.chart.geometries[0].elements[0].getData().sales).toBe(data[2].sales);
33+
expect(barPlot.chart.geometries[0].elements[0].getData().sales).toBe(data[0].sales);
3434
expect(barPlot.chart.getData()).toEqual(chartData);
3535

3636
barPlot.destroy();

__tests__/unit/adaptor/conversion-tag-spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ describe('bar conversion tag', () => {
257257

258258
const shapes = plot.chart.geometries[0].getShapes();
259259
const shapeBBoxes = shapes.map((shape) => shape.getBBox());
260-
const totalHeight = shapeBBoxes[0].minY - shapeBBoxes[1].maxY;
260+
const totalHeight = shapeBBoxes[1].minY - shapeBBoxes[0].maxY;
261261
const foreground = plot.chart.foregroundGroup;
262262

263263
// 整体
@@ -308,7 +308,7 @@ describe('bar conversion tag', () => {
308308

309309
const shapes = plot.chart.geometries[0].getShapes();
310310
const shapeBBoxes = shapes.map((shape) => shape.getBBox());
311-
const totalHeight = shapeBBoxes[0].minY - shapeBBoxes[1].maxY;
311+
const totalHeight = shapeBBoxes[1].minY - shapeBBoxes[0].maxY;
312312
const foreground = plot.chart.foregroundGroup;
313313

314314
// 整体

__tests__/unit/plots/bar/change-data-spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ describe('bar', () => {
9595
{ product_type: '电子产品', sex: '女', order_amt: 5.9, product_sub_type: '鼠标' },
9696
];
9797

98-
const dualAxes = new Bar(createDiv(), {
98+
const plot = new Bar(createDiv(), {
9999
data: [],
100100
xField: 'product_type',
101101
yField: 'order_amt',
@@ -105,15 +105,15 @@ describe('bar', () => {
105105
groupField: 'sex',
106106
});
107107

108-
dualAxes.render();
109-
dualAxes.changeData(data);
110-
const elements = dualAxes.chart.geometries[0].elements;
108+
plot.render();
109+
plot.changeData(data);
110+
const elements = plot.chart.geometries[0].elements;
111111
expect(elements.length).toBe(data.length);
112112
expect(elements[0].shape.attr('fill')).toBe(elements[1].shape.attr('fill'));
113-
// 从下至上绘制
114-
expect(elements[0].getModel().data).toMatchObject(data[data.length - 1]);
115-
expect(elements[1].getModel().data).toEqual(data[data.length - 2]);
113+
// 从下至上绘制 (数据不进行反转)
114+
expect(elements[0].getModel().data).toMatchObject(data[0]);
115+
expect(elements[1].getModel().data).toEqual(data[2]);
116116

117-
dualAxes.destroy();
117+
plot.destroy();
118118
});
119119
});

__tests__/unit/plots/bar/index-spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,15 @@ describe('bar', () => {
414414
bar.destroy();
415415
});
416416

417+
it('coordinate', () => {
418+
const plot = getBar(false, false);
419+
420+
expect(plot.chart.getCoordinate().isReflect('y')).toBe(true);
421+
expect(plot.chart.getCoordinate().isTransposed).toBe(true);
422+
423+
plot.destroy();
424+
});
425+
417426
it('update annotations', () => {
418427
const plot = new Bar(createDiv(), {
419428
data: salesByArea,

__tests__/unit/plots/bar/label-spec.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ describe('bar label', () => {
3232
});
3333
expect(labelGroups).toHaveLength(salesByArea.length);
3434
labelGroups.forEach((label, index) => {
35-
expect(label.get('children')[0].attr('text')).toBe(
36-
`${Math.floor(salesByArea[salesByArea.length - index - 1].sales / 10000)}万`
37-
);
35+
expect(label.get('children')[0].attr('text')).toBe(`${Math.floor(salesByArea[index].sales / 10000)}万`);
3836
});
3937

4038
bar.destroy();

__tests__/unit/plots/bar/pattern-spec.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ describe('bar style', () => {
5454

5555
const geometry = bar.chart.geometries[0];
5656
const elements = geometry.elements;
57-
expect(elements[2].shape.attr('fill') instanceof CanvasPattern).toEqual(true);
58-
expect(elements[0].shape.attr('fill') instanceof CanvasPattern).toEqual(false);
57+
expect(elements[3].shape.attr('fill') instanceof CanvasPattern).toEqual(true);
58+
expect(elements[2].shape.attr('fill') instanceof CanvasPattern).toEqual(false);
5959

6060
bar.update({
6161
pattern: ({ area }) => {
@@ -65,8 +65,10 @@ describe('bar style', () => {
6565
},
6666
});
6767

68-
expect(bar.chart.geometries[0].elements[0].shape.attr('fill') instanceof CanvasPattern).toEqual(true);
69-
expect(bar.chart.geometries[0].elements[1].shape.attr('fill') instanceof CanvasPattern).toEqual(false);
68+
expect(
69+
bar.chart.geometries[0].elements[salesByArea.length - 1].shape.attr('fill') instanceof CanvasPattern
70+
).toEqual(true);
71+
expect(bar.chart.geometries[0].elements[0].shape.attr('fill') instanceof CanvasPattern).toEqual(false);
7072

7173
bar.destroy();
7274
});

docs/api/plots/bar.zh.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,15 @@ order: 3
9999

100100
`markdown:docs/common/common-component.zh.md`
101101

102-
#### 缩略轴
102+
#### 缩略轴 slider
103103

104104
`markdown:docs/common/slider.zh.md`
105105

106-
#### 滚动条
106+
#### 滚动条 scrollbar
107107

108108
`markdown:docs/common/scrollbar.zh.md`
109109

110-
#### 转化标签
110+
#### 转化标签 conversionTag
111111

112112
适用于基础柱形图和基础条形图,转化率组件可以让用户关注到数据的变化比例。
113113

docs/api/plots/column.zh.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,21 @@ order: 2
101101

102102
`markdown:docs/common/common-component.zh.md`
103103

104-
#### 缩略轴
104+
#### 缩略轴 slider
105105

106106
`markdown:docs/common/slider.zh.md`
107107

108-
#### 滚动条
108+
#### 滚动条 scrollbar
109109

110110
`markdown:docs/common/scrollbar.zh.md`
111111

112-
#### 转化标签
112+
#### 转化标签 conversionTag
113113

114114
适用于基础柱形图和基础条形图,转化率组件可以让用户关注到数据的变化比例。
115115

116116
`markdown:docs/common/conversion-tag.zh.md`
117117

118-
#### 联通区域对比
118+
#### 联通区域对比 connectedArea
119119

120120
`markdown:docs/common/connected-area.zh.md`
121121

docs/api/plots/dual-axes.zh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ xAxis、yAxis 配置相同,由于 DualAxes 是双轴, annotations 类型是
173173

174174
`markdown:docs/common/theme.zh.md`
175175

176-
#### 缩略轴
176+
#### 缩略轴 slider
177177

178178
`markdown:docs/common/slider.zh.md`
179179

src/adaptor/conversion-tag.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ function renderArrowTag(config: TagRenderConfig, elemPrev: Element, elemNext: El
9090
const { view, geometry, group, options, horizontal } = config;
9191
const { offset, size, arrow } = options;
9292
const coordinate = view.getCoordinate();
93-
const pointPrev = parsePoints(coordinate, elemPrev)[horizontal ? 3 : 0];
94-
const pointNext = parsePoints(coordinate, elemNext)[horizontal ? 0 : 3];
93+
const pointPrev = parsePoints(coordinate, elemPrev)[3];
94+
const pointNext = parsePoints(coordinate, elemNext)[0];
9595
const totalHeight = pointNext.y - pointPrev.y;
9696
const totalWidth = pointNext.x - pointPrev.x;
9797

@@ -238,7 +238,7 @@ export function conversionTag<O extends OptionWithConversionTag & Options>(
238238
horizontal,
239239
options: getConversionTagOptionsWithDefaults(conversionTag, horizontal),
240240
};
241-
const elements = horizontal ? interval.elements : interval.elements.slice().reverse();
241+
const elements = interval.elements;
242242
each(elements, (elem: Element, idx: number) => {
243243
if (idx > 0) {
244244
renderTag(config, elements[idx - 1], elem);

src/plots/bar/adaptor.ts

Lines changed: 102 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,57 @@
11
import { Params } from '../../core/adaptor';
2+
import { deepAssign, flow } from '../../utils';
23
import { adaptor as columnAdaptor } from '../column/adaptor';
4+
export { meta } from '../column/adaptor';
35
import { BarOptions } from './types';
4-
import { transformBarData } from './utils';
56

6-
export { meta } from '../column/adaptor';
7+
/**
8+
* 处理默认配置项
9+
* 1. switch xField、 yField
10+
* 2. switch xAxis、 yAxis and adjust axis.position configuration
11+
*/
12+
function defaultOptions(params: Params<BarOptions>): Params<BarOptions> {
13+
const { options } = params;
14+
const { xField, yField, xAxis, yAxis } = options;
15+
16+
const position = {
17+
left: 'bottom',
18+
right: 'top',
19+
top: 'left',
20+
bottom: 'right',
21+
};
22+
23+
const verticalAxis =
24+
yAxis !== false
25+
? {
26+
position: position[yAxis?.position || 'left'],
27+
...yAxis,
28+
}
29+
: false;
30+
const horizontalAxis =
31+
xAxis !== false
32+
? {
33+
position: position[xAxis?.position || 'bottom'],
34+
...xAxis,
35+
}
36+
: false;
37+
38+
return deepAssign({}, params, {
39+
options: {
40+
xField: yField,
41+
yField: xField,
42+
xAxis: verticalAxis,
43+
yAxis: horizontalAxis,
44+
},
45+
});
46+
}
747

848
/**
9-
* 柱形图适配器
49+
* label 适配器
1050
* @param params
1151
*/
12-
export function adaptor(params: Params<BarOptions>) {
13-
const { chart, options } = params;
14-
const {
15-
xField,
16-
yField,
17-
xAxis,
18-
yAxis,
19-
barStyle,
20-
barWidthRatio,
21-
label,
22-
data,
23-
seriesField,
24-
isStack,
25-
minBarWidth,
26-
maxBarWidth,
27-
} = options;
28-
52+
function label(params: Params<BarOptions>): Params<BarOptions> {
53+
const { options } = params;
54+
const { label } = options;
2955
// label of bar charts default position is left, if plot has label
3056
if (label && !label.position) {
3157
label.position = 'left';
@@ -40,7 +66,18 @@ export function adaptor(params: Params<BarOptions>) {
4066
}
4167
}
4268

69+
return deepAssign({}, params, { options: { label } });
70+
}
71+
72+
/**
73+
* legend 适配器
74+
* @param params
75+
*/
76+
function legend(params: Params<BarOptions>): Params<BarOptions> {
77+
const { options } = params;
78+
4379
// 默认 legend 位置
80+
const { seriesField, isStack } = options;
4481
let { legend } = options;
4582
if (seriesField) {
4683
if (legend !== false) {
@@ -53,9 +90,19 @@ export function adaptor(params: Params<BarOptions>) {
5390
} else {
5491
legend = false;
5592
}
56-
// @ts-ignore 直接改值
57-
params.options.legend = legend;
5893

94+
return deepAssign({}, params, { options: { legend } });
95+
}
96+
97+
/**
98+
* tooltip 适配器
99+
* @param params
100+
*/
101+
function tooltip(params: Params<BarOptions>): Params<BarOptions> {
102+
const { options } = params;
103+
104+
// 默认 legend 位置
105+
const { seriesField, isStack } = options;
59106
// 默认 tooltip 配置
60107
let { tooltip } = options;
61108
if (seriesField) {
@@ -66,33 +113,52 @@ export function adaptor(params: Params<BarOptions>) {
66113
};
67114
}
68115
}
69-
// @ts-ignore 直接改值
70-
params.options.tooltip = tooltip;
71116

72-
// transpose column to bar
73-
chart.coordinate().transpose();
117+
return deepAssign({}, params, { options: { tooltip } });
118+
}
119+
120+
/**
121+
* coordinate 适配器
122+
* @param params
123+
*/
124+
function coordinate(params: Params<BarOptions>): Params<BarOptions> {
125+
const { chart } = params;
126+
// transpose column to bar 对角变换 & y 方向镜像变换
127+
chart.coordinate({ actions: [['transpose'], ['reflect', 'y']] });
128+
return params;
129+
}
130+
131+
/**
132+
* 柱形图适配器
133+
* @param params
134+
*/
135+
export function geometry(params: Params<BarOptions>) {
136+
const { chart, options } = params;
137+
138+
const { barStyle, barWidthRatio, minBarWidth, maxBarWidth, barBackground } = options;
74139

75140
return columnAdaptor(
76141
{
77142
chart,
78143
options: {
79144
...options,
80-
label,
81-
// switch xField and yField
82-
xField: yField,
83-
yField: xField,
84-
xAxis: yAxis,
85-
yAxis: xAxis,
86145
// rename attrs as column
87146
columnStyle: barStyle,
88147
columnWidthRatio: barWidthRatio,
89148
minColumnWidth: minBarWidth,
90149
maxColumnWidth: maxBarWidth,
91-
columnBackground: options.barBackground,
92-
// bar 调整数据顺序
93-
data: transformBarData(data),
150+
columnBackground: barBackground,
94151
},
95152
},
96153
true
97-
);
154+
) as Params<BarOptions>;
155+
}
156+
157+
/**
158+
* @param chart
159+
* @param options
160+
*/
161+
export function adaptor(params: Params<BarOptions>): Params<BarOptions> {
162+
// flow 的方式处理所有的配置到 G2 API
163+
return flow<Params<BarOptions>>(defaultOptions, label, legend, tooltip, coordinate, geometry)(params);
98164
}

src/plots/bar/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { getDataWhetherPecentage } from '../../utils/transform/percent';
44
import { BarOptions } from './types';
55
import { adaptor, meta } from './adaptor';
66
import { DEFAULT_OPTIONS } from './constants';
7-
import { transformBarData } from './utils';
87

98
export type { BarOptions };
109

@@ -32,7 +31,7 @@ export class Bar extends Plot<BarOptions> {
3231
const { xField, yField, isPercent } = options;
3332
const switchedFieldOptions = { ...options, xField: yField, yField: xField };
3433
meta({ chart, options: switchedFieldOptions });
35-
chart.changeData(getDataWhetherPecentage(transformBarData(data), xField, yField, xField, isPercent));
34+
chart.changeData(getDataWhetherPecentage(data, xField, yField, xField, isPercent));
3635
}
3736

3837
/**

src/plots/bar/utils.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)