Skip to content

Commit

Permalink
refactor(bar): 条形图重构,不需要反转数据 调整下坐标系即可 (#2914)
Browse files Browse the repository at this point in the history
* refactor(bar): 条形图重构,不需要反转数据 调整下坐标系即可

需要 G2 层支持对 scrollbar 反转

* feat(bar): 条形图数据不进行反转 & 修改单测

* fix(conversion-bar): 修复转化率组件在 vertical 方向的位置问题 & 单测

* test: 修复条形图单测
  • Loading branch information
visiky authored Nov 27, 2021
1 parent 69087ae commit b1d8f47
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 76 deletions.
2 changes: 1 addition & 1 deletion __tests__/bugs/bar-changedata-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('bar changeData should keep order', () => {
barPlot.changeData(data);

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

barPlot.destroy();
Expand Down
4 changes: 2 additions & 2 deletions __tests__/unit/adaptor/conversion-tag-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ describe('bar conversion tag', () => {

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

// 整体
Expand Down Expand Up @@ -308,7 +308,7 @@ describe('bar conversion tag', () => {

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

// 整体
Expand Down
16 changes: 8 additions & 8 deletions __tests__/unit/plots/bar/change-data-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('bar', () => {
{ product_type: '电子产品', sex: '女', order_amt: 5.9, product_sub_type: '鼠标' },
];

const dualAxes = new Bar(createDiv(), {
const plot = new Bar(createDiv(), {
data: [],
xField: 'product_type',
yField: 'order_amt',
Expand All @@ -105,15 +105,15 @@ describe('bar', () => {
groupField: 'sex',
});

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

dualAxes.destroy();
plot.destroy();
});
});
9 changes: 9 additions & 0 deletions __tests__/unit/plots/bar/index-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,15 @@ describe('bar', () => {
bar.destroy();
});

it('coordinate', () => {
const plot = getBar(false, false);

expect(plot.chart.getCoordinate().isReflect('y')).toBe(true);
expect(plot.chart.getCoordinate().isTransposed).toBe(true);

plot.destroy();
});

it('update annotations', () => {
const plot = new Bar(createDiv(), {
data: salesByArea,
Expand Down
4 changes: 1 addition & 3 deletions __tests__/unit/plots/bar/label-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ describe('bar label', () => {
});
expect(labelGroups).toHaveLength(salesByArea.length);
labelGroups.forEach((label, index) => {
expect(label.get('children')[0].attr('text')).toBe(
`${Math.floor(salesByArea[salesByArea.length - index - 1].sales / 10000)}万`
);
expect(label.get('children')[0].attr('text')).toBe(`${Math.floor(salesByArea[index].sales / 10000)}万`);
});

bar.destroy();
Expand Down
10 changes: 6 additions & 4 deletions __tests__/unit/plots/bar/pattern-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ describe('bar style', () => {

const geometry = bar.chart.geometries[0];
const elements = geometry.elements;
expect(elements[2].shape.attr('fill') instanceof CanvasPattern).toEqual(true);
expect(elements[0].shape.attr('fill') instanceof CanvasPattern).toEqual(false);
expect(elements[3].shape.attr('fill') instanceof CanvasPattern).toEqual(true);
expect(elements[2].shape.attr('fill') instanceof CanvasPattern).toEqual(false);

bar.update({
pattern: ({ area }) => {
Expand All @@ -65,8 +65,10 @@ describe('bar style', () => {
},
});

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

bar.destroy();
});
Expand Down
6 changes: 3 additions & 3 deletions docs/api/plots/bar.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ order: 3

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

#### 缩略轴
#### 缩略轴 slider

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

#### 滚动条
#### 滚动条 scrollbar

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

#### 转化标签
#### 转化标签 conversionTag

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

Expand Down
8 changes: 4 additions & 4 deletions docs/api/plots/column.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,21 +101,21 @@ order: 2

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

#### 缩略轴
#### 缩略轴 slider

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

#### 滚动条
#### 滚动条 scrollbar

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

#### 转化标签
#### 转化标签 conversionTag

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

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

#### 联通区域对比
#### 联通区域对比 connectedArea

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

Expand Down
2 changes: 1 addition & 1 deletion docs/api/plots/dual-axes.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ xAxis、yAxis 配置相同,由于 DualAxes 是双轴, annotations 类型是

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

#### 缩略轴
#### 缩略轴 slider

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

Expand Down
6 changes: 3 additions & 3 deletions src/adaptor/conversion-tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ function renderArrowTag(config: TagRenderConfig, elemPrev: Element, elemNext: El
const { view, geometry, group, options, horizontal } = config;
const { offset, size, arrow } = options;
const coordinate = view.getCoordinate();
const pointPrev = parsePoints(coordinate, elemPrev)[horizontal ? 3 : 0];
const pointNext = parsePoints(coordinate, elemNext)[horizontal ? 0 : 3];
const pointPrev = parsePoints(coordinate, elemPrev)[3];
const pointNext = parsePoints(coordinate, elemNext)[0];
const totalHeight = pointNext.y - pointPrev.y;
const totalWidth = pointNext.x - pointPrev.x;

Expand Down Expand Up @@ -238,7 +238,7 @@ export function conversionTag<O extends OptionWithConversionTag & Options>(
horizontal,
options: getConversionTagOptionsWithDefaults(conversionTag, horizontal),
};
const elements = horizontal ? interval.elements : interval.elements.slice().reverse();
const elements = interval.elements;
each(elements, (elem: Element, idx: number) => {
if (idx > 0) {
renderTag(config, elements[idx - 1], elem);
Expand Down
138 changes: 102 additions & 36 deletions src/plots/bar/adaptor.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,57 @@
import { Params } from '../../core/adaptor';
import { deepAssign, flow } from '../../utils';
import { adaptor as columnAdaptor } from '../column/adaptor';
export { meta } from '../column/adaptor';
import { BarOptions } from './types';
import { transformBarData } from './utils';

export { meta } from '../column/adaptor';
/**
* 处理默认配置项
* 1. switch xField、 yField
* 2. switch xAxis、 yAxis and adjust axis.position configuration
*/
function defaultOptions(params: Params<BarOptions>): Params<BarOptions> {
const { options } = params;
const { xField, yField, xAxis, yAxis } = options;

const position = {
left: 'bottom',
right: 'top',
top: 'left',
bottom: 'right',
};

const verticalAxis =
yAxis !== false
? {
position: position[yAxis?.position || 'left'],
...yAxis,
}
: false;
const horizontalAxis =
xAxis !== false
? {
position: position[xAxis?.position || 'bottom'],
...xAxis,
}
: false;

return deepAssign({}, params, {
options: {
xField: yField,
yField: xField,
xAxis: verticalAxis,
yAxis: horizontalAxis,
},
});
}

/**
* 柱形图适配器
* label 适配器
* @param params
*/
export function adaptor(params: Params<BarOptions>) {
const { chart, options } = params;
const {
xField,
yField,
xAxis,
yAxis,
barStyle,
barWidthRatio,
label,
data,
seriesField,
isStack,
minBarWidth,
maxBarWidth,
} = options;

function label(params: Params<BarOptions>): Params<BarOptions> {
const { options } = params;
const { label } = options;
// label of bar charts default position is left, if plot has label
if (label && !label.position) {
label.position = 'left';
Expand All @@ -40,7 +66,18 @@ export function adaptor(params: Params<BarOptions>) {
}
}

return deepAssign({}, params, { options: { label } });
}

/**
* legend 适配器
* @param params
*/
function legend(params: Params<BarOptions>): Params<BarOptions> {
const { options } = params;

// 默认 legend 位置
const { seriesField, isStack } = options;
let { legend } = options;
if (seriesField) {
if (legend !== false) {
Expand All @@ -53,9 +90,19 @@ export function adaptor(params: Params<BarOptions>) {
} else {
legend = false;
}
// @ts-ignore 直接改值
params.options.legend = legend;

return deepAssign({}, params, { options: { legend } });
}

/**
* tooltip 适配器
* @param params
*/
function tooltip(params: Params<BarOptions>): Params<BarOptions> {
const { options } = params;

// 默认 legend 位置
const { seriesField, isStack } = options;
// 默认 tooltip 配置
let { tooltip } = options;
if (seriesField) {
Expand All @@ -66,33 +113,52 @@ export function adaptor(params: Params<BarOptions>) {
};
}
}
// @ts-ignore 直接改值
params.options.tooltip = tooltip;

// transpose column to bar
chart.coordinate().transpose();
return deepAssign({}, params, { options: { tooltip } });
}

/**
* coordinate 适配器
* @param params
*/
function coordinate(params: Params<BarOptions>): Params<BarOptions> {
const { chart } = params;
// transpose column to bar 对角变换 & y 方向镜像变换
chart.coordinate({ actions: [['transpose'], ['reflect', 'y']] });
return params;
}

/**
* 柱形图适配器
* @param params
*/
export function geometry(params: Params<BarOptions>) {
const { chart, options } = params;

const { barStyle, barWidthRatio, minBarWidth, maxBarWidth, barBackground } = options;

return columnAdaptor(
{
chart,
options: {
...options,
label,
// switch xField and yField
xField: yField,
yField: xField,
xAxis: yAxis,
yAxis: xAxis,
// rename attrs as column
columnStyle: barStyle,
columnWidthRatio: barWidthRatio,
minColumnWidth: minBarWidth,
maxColumnWidth: maxBarWidth,
columnBackground: options.barBackground,
// bar 调整数据顺序
data: transformBarData(data),
columnBackground: barBackground,
},
},
true
);
) as Params<BarOptions>;
}

/**
* @param chart
* @param options
*/
export function adaptor(params: Params<BarOptions>): Params<BarOptions> {
// flow 的方式处理所有的配置到 G2 API
return flow<Params<BarOptions>>(defaultOptions, label, legend, tooltip, coordinate, geometry)(params);
}
3 changes: 1 addition & 2 deletions src/plots/bar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getDataWhetherPecentage } from '../../utils/transform/percent';
import { BarOptions } from './types';
import { adaptor, meta } from './adaptor';
import { DEFAULT_OPTIONS } from './constants';
import { transformBarData } from './utils';

export type { BarOptions };

Expand Down Expand Up @@ -32,7 +31,7 @@ export class Bar extends Plot<BarOptions> {
const { xField, yField, isPercent } = options;
const switchedFieldOptions = { ...options, xField: yField, yField: xField };
meta({ chart, options: switchedFieldOptions });
chart.changeData(getDataWhetherPecentage(transformBarData(data), xField, yField, xField, isPercent));
chart.changeData(getDataWhetherPecentage(data, xField, yField, xField, isPercent));
}

/**
Expand Down
9 changes: 0 additions & 9 deletions src/plots/bar/utils.ts

This file was deleted.

0 comments on commit b1d8f47

Please sign in to comment.