Skip to content

Commit 4e7e022

Browse files
authored
fix(#1870): when y are same in dual-axes, axis position is wrong (#1878)
* fix(#1870): when y are same in dual-axes, axis position is wrong * chore: update type define * test: inc coverage * fix: cr
1 parent d88a3fa commit 4e7e022

File tree

6 files changed

+206
-69
lines changed

6 files changed

+206
-69
lines changed

__tests__/bugs/issue-1870-spec.ts

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { DualAxes } from '../../src';
2+
import { createDiv } from '../utils/dom';
3+
4+
const uvBillData = [
5+
{ time: '2019-03', value: 350, type: 'uv' },
6+
{ time: '2019-04', value: 900, type: 'uv' },
7+
{ time: '2019-05', value: 300, type: 'uv' },
8+
{ time: '2019-06', value: 450, type: 'uv' },
9+
{ time: '2019-07', value: 470, type: 'uv' },
10+
{ time: '2019-03', value: 220, type: 'bill' },
11+
{ time: '2019-04', value: 300, type: 'bill' },
12+
{ time: '2019-05', value: 250, type: 'bill' },
13+
{ time: '2019-06', value: 220, type: 'bill' },
14+
{ time: '2019-07', value: 362, type: 'bill' },
15+
];
16+
17+
const transformData = [
18+
{ time: '2019-03', value: 800, name: 'a' },
19+
{ time: '2019-04', value: 600, name: 'a' },
20+
{ time: '2019-05', value: 400, name: 'a' },
21+
{ time: '2019-06', value: 380, name: 'a' },
22+
{ time: '2019-07', value: 220, name: 'a' },
23+
{ time: '2019-03', value: 750, name: 'b' },
24+
{ time: '2019-04', value: 650, name: 'b' },
25+
{ time: '2019-05', value: 450, name: 'b' },
26+
{ time: '2019-06', value: 400, name: 'b' },
27+
{ time: '2019-07', value: 320, name: 'b' },
28+
{ time: '2019-03', value: 900, name: 'c' },
29+
{ time: '2019-04', value: 600, name: 'c' },
30+
{ time: '2019-05', value: 450, name: 'c' },
31+
{ time: '2019-06', value: 300, name: 'c' },
32+
{ time: '2019-07', value: 200, name: 'c' },
33+
];
34+
35+
describe('#1870', () => {
36+
it('1870', () => {
37+
const dualAxes = new DualAxes(createDiv(), {
38+
data: [uvBillData, transformData],
39+
xField: 'time',
40+
yField: ['value', 'value'],
41+
geometryOptions: [
42+
{
43+
geometry: 'column',
44+
isGroup: true,
45+
seriesField: 'type',
46+
columnWidthRatio: 0.4,
47+
color: ['#5B8FF9', '#5AD8A6'],
48+
},
49+
{
50+
geometry: 'line',
51+
seriesField: 'name',
52+
color: ['#CDDDFD', '#CDF3E4', '#CED4DE'],
53+
lineStyle: ({ name }) => {
54+
if (name === 'a') {
55+
return {
56+
lineDash: [2, 2],
57+
opacity: 1,
58+
};
59+
}
60+
return {
61+
opacity: 0.5,
62+
};
63+
},
64+
},
65+
],
66+
});
67+
68+
dualAxes.render();
69+
70+
// @ts-ignore
71+
expect(dualAxes.chart.views[0].getOptions().axes.value).toEqual({
72+
label: {
73+
autoHide: true,
74+
autoRotate: false,
75+
},
76+
nice: true,
77+
position: 'left',
78+
});
79+
// @ts-ignore
80+
expect(dualAxes.chart.views[1].getOptions().axes.value).toEqual({
81+
label: {
82+
autoHide: true,
83+
autoRotate: false,
84+
},
85+
nice: true,
86+
grid: null,
87+
position: 'right',
88+
});
89+
90+
dualAxes.destroy();
91+
});
92+
});

__tests__/unit/plots/dual-axes/util/option-spec.ts

+46-27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import { isLine, isColumn, getGeometryOption, getDefaultYAxis } from '../../../../../src/plots/dual-axes/util/option';
2-
1+
import {
2+
isLine,
3+
isColumn,
4+
getGeometryOption,
5+
getCompatibleYAxis,
6+
getYAxisWithDefault,
7+
} from '../../../../../src/plots/dual-axes/util/option';
38
import { AxisType } from '../../../../../src/plots/dual-axes/types';
49

510
const DEFAULT_LEFT_YAXIS_CONFIG = {
@@ -32,42 +37,56 @@ describe('DualAxes option', () => {
3237
expect(isColumn({ geometry: 'column' })).toBe(true);
3338
});
3439

35-
it('getDefaultYAxis', () => {
36-
expect(getDefaultYAxis(['yField1', 'yField2'], undefined)).toEqual({
37-
yField1: DEFAULT_LEFT_YAXIS_CONFIG,
38-
yField2: DEFAULT_RIGHT_YAXIS_CONFIG,
40+
it('getCompatibleYAxis', () => {
41+
expect(getCompatibleYAxis(['yField1', 'yField2'], undefined)).toEqual({
42+
yField1: undefined,
43+
yField2: undefined,
3944
});
40-
});
41-
it('yAxis option', () => {
42-
expect(getDefaultYAxis(['yField1', 'yField2'], {})).toEqual({
43-
yField1: DEFAULT_LEFT_YAXIS_CONFIG,
44-
yField2: DEFAULT_RIGHT_YAXIS_CONFIG,
45+
46+
expect(getCompatibleYAxis(['yField1', 'yField2'], [{ nice: false }])).toEqual({
47+
yField1: { nice: false },
48+
yField2: undefined,
4549
});
4650

47-
// @ts-ignore
48-
expect(getDefaultYAxis(['yField1', 'yField2'], { yField1: { a: 1 }, yField2: false })).toEqual({
49-
yField1: {
50-
...DEFAULT_LEFT_YAXIS_CONFIG,
51-
a: 1,
52-
},
53-
yField2: false,
51+
expect(getCompatibleYAxis(['yField1', 'yField2'], [false])).toEqual({
52+
yField1: false,
53+
yField2: undefined,
5454
});
5555

56-
expect(getDefaultYAxis(['yField1', 'yField2'], [])).toEqual({
57-
yField1: DEFAULT_LEFT_YAXIS_CONFIG,
58-
yField2: DEFAULT_RIGHT_YAXIS_CONFIG,
56+
expect(getCompatibleYAxis(['yField1', 'yField2'], { yField1: { nice: true } })).toEqual({
57+
yField1: { nice: true },
58+
yField2: undefined,
5959
});
6060

61-
// @ts-ignore
62-
expect(getDefaultYAxis(['yField1', 'yField2'], [{ a: 1 }, false])).toEqual({
63-
yField1: {
64-
...DEFAULT_LEFT_YAXIS_CONFIG,
65-
a: 1,
66-
},
61+
expect(getCompatibleYAxis(['yField1', 'yField2'], { yField1: { nice: true }, yField2: false })).toEqual({
62+
yField1: { nice: true },
6763
yField2: false,
6864
});
6965
});
7066

67+
it('getDefaultYAxis', () => {
68+
expect(getYAxisWithDefault(undefined, AxisType.Left)).toEqual(DEFAULT_LEFT_YAXIS_CONFIG);
69+
expect(getYAxisWithDefault({}, AxisType.Left)).toEqual(DEFAULT_LEFT_YAXIS_CONFIG);
70+
expect(getYAxisWithDefault(false, AxisType.Left)).toBe(false);
71+
expect(getYAxisWithDefault({ type: 'cat' }, AxisType.Left)).toEqual({ ...DEFAULT_LEFT_YAXIS_CONFIG, type: 'cat' });
72+
expect(getYAxisWithDefault({ nice: false }, AxisType.Left)).toEqual({ ...DEFAULT_LEFT_YAXIS_CONFIG, nice: false });
73+
74+
expect(getYAxisWithDefault(undefined, AxisType.Right)).toEqual(DEFAULT_RIGHT_YAXIS_CONFIG);
75+
expect(getYAxisWithDefault({}, AxisType.Right)).toEqual(DEFAULT_RIGHT_YAXIS_CONFIG);
76+
expect(getYAxisWithDefault(false, AxisType.Right)).toBe(false);
77+
expect(getYAxisWithDefault({ type: 'cat' }, AxisType.Right)).toEqual({
78+
...DEFAULT_RIGHT_YAXIS_CONFIG,
79+
type: 'cat',
80+
});
81+
expect(getYAxisWithDefault({ nice: false }, AxisType.Right)).toEqual({
82+
...DEFAULT_RIGHT_YAXIS_CONFIG,
83+
nice: false,
84+
});
85+
86+
// @ts-ignore
87+
expect(getYAxisWithDefault({ type: 'log' }, 'xxx')).toEqual({ type: 'log' });
88+
});
89+
7190
it('getGeometryOption', () => {
7291
expect(getGeometryOption('test', 'yField1', undefined, AxisType.Left)).toEqual({
7392
geometry: 'line',

src/plots/dual-axes/adaptor.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import {
88
} from '../../adaptor/common';
99
import { percent } from '../../utils/transform/percent';
1010
import { Params } from '../../core/adaptor';
11+
import { Datum } from '../../types';
1112
import { flow, deepAssign } from '../../utils';
1213
import { findViewById } from '../../utils/view';
13-
import { Datum } from '../../types';
14-
import { isColumn, getDefaultYAxis, getGeometryOption } from './util/option';
14+
import { isColumn, getYAxisWithDefault, getGeometryOption, getCompatibleYAxis } from './util/option';
1515
import { getViewLegendItems } from './util/legend';
1616
import { drawSingleGeometry } from './util/geometry';
1717
import { DualAxesOptions, AxisType, DualAxesGeometry } from './types';
@@ -55,7 +55,7 @@ export function transformOptions(params: Params<DualAxesOptions>): Params<DualAx
5555
? [{ type: 'legend-visible-filter' }, { type: 'active-region' }]
5656
: [{ type: 'legend-visible-filter' }],
5757
// yAxis
58-
yAxis: getDefaultYAxis(yField, options.yAxis),
58+
yAxis: getCompatibleYAxis(yField, options.yAxis),
5959
// geometryOptions
6060
geometryOptions: [
6161
getGeometryOption(xField, yField[0], geometryOptions[0], AxisType.Left),
@@ -152,11 +152,11 @@ export function axis(params: Params<DualAxesOptions>): Params<DualAxesOptions> {
152152

153153
// 左 View
154154
leftView.axis(xField, xAxis);
155-
leftView.axis(yField[0], yAxis[yField[0]]);
155+
leftView.axis(yField[0], getYAxisWithDefault(yAxis[yField[0]], AxisType.Left));
156156

157157
// 右 Y 轴
158158
rightView.axis(xField, false);
159-
rightView.axis(yField[1], yAxis[yField[1]]);
159+
rightView.axis(yField[1], getYAxisWithDefault(yAxis[yField[1]], AxisType.Right));
160160

161161
return params;
162162
}

src/plots/dual-axes/constant.ts

+19
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,21 @@
11
export const LEFT_AXES_VIEW = 'left-axes-view';
22
export const RIGHT_AXES_VIEW = 'right-axes-view';
3+
4+
export const DEFAULT_YAXIS_CONFIG = {
5+
nice: true,
6+
label: {
7+
autoHide: true,
8+
autoRotate: false,
9+
},
10+
};
11+
12+
export const DEFAULT_LEFT_YAXIS_CONFIG = {
13+
...DEFAULT_YAXIS_CONFIG,
14+
position: 'left',
15+
};
16+
17+
export const DEFAULT_RIGHT_YAXIS_CONFIG = {
18+
...DEFAULT_YAXIS_CONFIG,
19+
position: 'right',
20+
grid: null,
21+
};

src/plots/dual-axes/types.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,27 @@ export type GeometryColumnOption = Pick<
4444
export type GeometryOption = GeometryColumnOption | GeometryLineOption;
4545

4646
export type DualAxesOptions = Omit<Options, 'data' | 'yAxis' | 'color'> & {
47-
// 通用数据配置
48-
/** 具体的数据 */
47+
/**
48+
* 具体的数据,左右两边的数据
49+
*/
4950
readonly data: Array<Record<string, any>[]>;
5051

52+
/**
53+
* 双轴图的 x 字段,x 字段名称需要保持一致
54+
*/
5155
readonly xField: string;
56+
/**
57+
* 双轴图左右 y 字段,需要不一致
58+
*/
5259
readonly yField: string[];
5360

54-
readonly geometryOptions?: GeometryOption[];
61+
/**
62+
* 左右两边的 yAxis 配置,使用 object 的方式,key 为 y 字段名,或者数组分别表示左右
63+
*/
64+
readonly yAxis?: Options['yAxis'][] | Record<string, Options['yAxis']>;
5565

56-
readonly yAxis?: Record<string, Options['yAxis']> | Options['yAxis'][];
66+
/**
67+
* 左右两边的图形配置
68+
*/
69+
readonly geometryOptions?: GeometryOption[];
5770
};

src/plots/dual-axes/util/option.ts

+27-33
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { get, isArray } from '@antv/util';
2+
import { Axis } from '../../../types/axis';
23
import { deepAssign } from '../../../utils';
34
import {
45
DualAxesOptions,
@@ -8,6 +9,7 @@ import {
89
GeometryColumnOption,
910
AxisType,
1011
} from '../types';
12+
import { DEFAULT_LEFT_YAXIS_CONFIG, DEFAULT_RIGHT_YAXIS_CONFIG } from '../constant';
1113

1214
/**
1315
* 根据 GeometryOption 判断 geometry 是否为 line
@@ -58,43 +60,35 @@ export function getGeometryOption(
5860
};
5961
}
6062

61-
export function getDefaultYAxis(
63+
/**
64+
* 兼容 yAxis 为 arr 和 obj 的两种情况
65+
* @param yField
66+
* @param yAxis
67+
*/
68+
export function getCompatibleYAxis(
6269
yField: DualAxesOptions['yField'],
63-
yAxis: DualAxesOptions['yAxis']
70+
yAxis: Record<string, Axis> | Axis[]
6471
): DualAxesOptions['yAxis'] {
65-
const DEFAULT_YAXIS_CONFIG = {
66-
nice: true,
67-
label: {
68-
autoHide: true,
69-
autoRotate: false,
70-
},
71-
};
72-
73-
const DEFAULT_LEFT_YAXIS_CONFIG = {
74-
...DEFAULT_YAXIS_CONFIG,
75-
position: 'left',
76-
};
77-
78-
const DEFAULT_RIGHT_YAXIS_CONFIG = {
79-
...DEFAULT_YAXIS_CONFIG,
80-
position: 'right',
81-
grid: null,
82-
};
83-
72+
const [y1, y2] = yField;
8473
if (isArray(yAxis)) {
8574
console.warn('yAxis should be object.');
86-
return {
87-
[yField[0]]: yAxis[0] !== false ? deepAssign({}, DEFAULT_LEFT_YAXIS_CONFIG, yAxis[0]) : false,
88-
[yField[1]]: yAxis[1] !== false ? deepAssign({}, DEFAULT_RIGHT_YAXIS_CONFIG, yAxis[1]) : false,
89-
};
75+
return { [y1]: yAxis[0], [y2]: yAxis[1] };
9076
}
9177

92-
return deepAssign(
93-
{},
94-
{
95-
[yField[0]]: DEFAULT_LEFT_YAXIS_CONFIG,
96-
[yField[1]]: DEFAULT_RIGHT_YAXIS_CONFIG,
97-
},
98-
yAxis
99-
);
78+
// 追加默认值
79+
return deepAssign({ [y1]: undefined, [y2]: undefined }, yAxis);
80+
}
81+
82+
/**
83+
* 获取默认值
84+
* @param yAxis
85+
* @param axisType
86+
*/
87+
export function getYAxisWithDefault(yAxis: Axis, axisType: AxisType): Axis {
88+
if (axisType === AxisType.Left) {
89+
return yAxis === false ? false : deepAssign({}, DEFAULT_LEFT_YAXIS_CONFIG, yAxis);
90+
} else if (axisType === AxisType.Right) {
91+
return yAxis === false ? false : deepAssign({}, DEFAULT_RIGHT_YAXIS_CONFIG, yAxis);
92+
}
93+
return yAxis;
10094
}

0 commit comments

Comments
 (0)