diff --git a/__tests__/bugs/issue-1870-spec.ts b/__tests__/bugs/issue-1870-spec.ts new file mode 100644 index 0000000000..b202b923a1 --- /dev/null +++ b/__tests__/bugs/issue-1870-spec.ts @@ -0,0 +1,92 @@ +import { DualAxes } from '../../src'; +import { createDiv } from '../utils/dom'; + +const uvBillData = [ + { time: '2019-03', value: 350, type: 'uv' }, + { time: '2019-04', value: 900, type: 'uv' }, + { time: '2019-05', value: 300, type: 'uv' }, + { time: '2019-06', value: 450, type: 'uv' }, + { time: '2019-07', value: 470, type: 'uv' }, + { time: '2019-03', value: 220, type: 'bill' }, + { time: '2019-04', value: 300, type: 'bill' }, + { time: '2019-05', value: 250, type: 'bill' }, + { time: '2019-06', value: 220, type: 'bill' }, + { time: '2019-07', value: 362, type: 'bill' }, +]; + +const transformData = [ + { time: '2019-03', value: 800, name: 'a' }, + { time: '2019-04', value: 600, name: 'a' }, + { time: '2019-05', value: 400, name: 'a' }, + { time: '2019-06', value: 380, name: 'a' }, + { time: '2019-07', value: 220, name: 'a' }, + { time: '2019-03', value: 750, name: 'b' }, + { time: '2019-04', value: 650, name: 'b' }, + { time: '2019-05', value: 450, name: 'b' }, + { time: '2019-06', value: 400, name: 'b' }, + { time: '2019-07', value: 320, name: 'b' }, + { time: '2019-03', value: 900, name: 'c' }, + { time: '2019-04', value: 600, name: 'c' }, + { time: '2019-05', value: 450, name: 'c' }, + { time: '2019-06', value: 300, name: 'c' }, + { time: '2019-07', value: 200, name: 'c' }, +]; + +describe('#1870', () => { + it('1870', () => { + const dualAxes = new DualAxes(createDiv(), { + data: [uvBillData, transformData], + xField: 'time', + yField: ['value', 'value'], + geometryOptions: [ + { + geometry: 'column', + isGroup: true, + seriesField: 'type', + columnWidthRatio: 0.4, + color: ['#5B8FF9', '#5AD8A6'], + }, + { + geometry: 'line', + seriesField: 'name', + color: ['#CDDDFD', '#CDF3E4', '#CED4DE'], + lineStyle: ({ name }) => { + if (name === 'a') { + return { + lineDash: [2, 2], + opacity: 1, + }; + } + return { + opacity: 0.5, + }; + }, + }, + ], + }); + + dualAxes.render(); + + // @ts-ignore + expect(dualAxes.chart.views[0].getOptions().axes.value).toEqual({ + label: { + autoHide: true, + autoRotate: false, + }, + nice: true, + position: 'left', + }); + // @ts-ignore + expect(dualAxes.chart.views[1].getOptions().axes.value).toEqual({ + label: { + autoHide: true, + autoRotate: false, + }, + nice: true, + grid: null, + position: 'right', + }); + + dualAxes.destroy(); + }); +}); diff --git a/__tests__/unit/plots/dual-axes/util/option-spec.ts b/__tests__/unit/plots/dual-axes/util/option-spec.ts index ab66c013ab..b483e9c4c6 100644 --- a/__tests__/unit/plots/dual-axes/util/option-spec.ts +++ b/__tests__/unit/plots/dual-axes/util/option-spec.ts @@ -1,5 +1,10 @@ -import { isLine, isColumn, getGeometryOption, getDefaultYAxis } from '../../../../../src/plots/dual-axes/util/option'; - +import { + isLine, + isColumn, + getGeometryOption, + getCompatibleYAxis, + getYAxisWithDefault, +} from '../../../../../src/plots/dual-axes/util/option'; import { AxisType } from '../../../../../src/plots/dual-axes/types'; const DEFAULT_LEFT_YAXIS_CONFIG = { @@ -32,42 +37,56 @@ describe('DualAxes option', () => { expect(isColumn({ geometry: 'column' })).toBe(true); }); - it('getDefaultYAxis', () => { - expect(getDefaultYAxis(['yField1', 'yField2'], undefined)).toEqual({ - yField1: DEFAULT_LEFT_YAXIS_CONFIG, - yField2: DEFAULT_RIGHT_YAXIS_CONFIG, + it('getCompatibleYAxis', () => { + expect(getCompatibleYAxis(['yField1', 'yField2'], undefined)).toEqual({ + yField1: undefined, + yField2: undefined, }); - }); - it('yAxis option', () => { - expect(getDefaultYAxis(['yField1', 'yField2'], {})).toEqual({ - yField1: DEFAULT_LEFT_YAXIS_CONFIG, - yField2: DEFAULT_RIGHT_YAXIS_CONFIG, + + expect(getCompatibleYAxis(['yField1', 'yField2'], [{ nice: false }])).toEqual({ + yField1: { nice: false }, + yField2: undefined, }); - // @ts-ignore - expect(getDefaultYAxis(['yField1', 'yField2'], { yField1: { a: 1 }, yField2: false })).toEqual({ - yField1: { - ...DEFAULT_LEFT_YAXIS_CONFIG, - a: 1, - }, - yField2: false, + expect(getCompatibleYAxis(['yField1', 'yField2'], [false])).toEqual({ + yField1: false, + yField2: undefined, }); - expect(getDefaultYAxis(['yField1', 'yField2'], [])).toEqual({ - yField1: DEFAULT_LEFT_YAXIS_CONFIG, - yField2: DEFAULT_RIGHT_YAXIS_CONFIG, + expect(getCompatibleYAxis(['yField1', 'yField2'], { yField1: { nice: true } })).toEqual({ + yField1: { nice: true }, + yField2: undefined, }); - // @ts-ignore - expect(getDefaultYAxis(['yField1', 'yField2'], [{ a: 1 }, false])).toEqual({ - yField1: { - ...DEFAULT_LEFT_YAXIS_CONFIG, - a: 1, - }, + expect(getCompatibleYAxis(['yField1', 'yField2'], { yField1: { nice: true }, yField2: false })).toEqual({ + yField1: { nice: true }, yField2: false, }); }); + it('getDefaultYAxis', () => { + expect(getYAxisWithDefault(undefined, AxisType.Left)).toEqual(DEFAULT_LEFT_YAXIS_CONFIG); + expect(getYAxisWithDefault({}, AxisType.Left)).toEqual(DEFAULT_LEFT_YAXIS_CONFIG); + expect(getYAxisWithDefault(false, AxisType.Left)).toBe(false); + expect(getYAxisWithDefault({ type: 'cat' }, AxisType.Left)).toEqual({ ...DEFAULT_LEFT_YAXIS_CONFIG, type: 'cat' }); + expect(getYAxisWithDefault({ nice: false }, AxisType.Left)).toEqual({ ...DEFAULT_LEFT_YAXIS_CONFIG, nice: false }); + + expect(getYAxisWithDefault(undefined, AxisType.Right)).toEqual(DEFAULT_RIGHT_YAXIS_CONFIG); + expect(getYAxisWithDefault({}, AxisType.Right)).toEqual(DEFAULT_RIGHT_YAXIS_CONFIG); + expect(getYAxisWithDefault(false, AxisType.Right)).toBe(false); + expect(getYAxisWithDefault({ type: 'cat' }, AxisType.Right)).toEqual({ + ...DEFAULT_RIGHT_YAXIS_CONFIG, + type: 'cat', + }); + expect(getYAxisWithDefault({ nice: false }, AxisType.Right)).toEqual({ + ...DEFAULT_RIGHT_YAXIS_CONFIG, + nice: false, + }); + + // @ts-ignore + expect(getYAxisWithDefault({ type: 'log' }, 'xxx')).toEqual({ type: 'log' }); + }); + it('getGeometryOption', () => { expect(getGeometryOption('test', 'yField1', undefined, AxisType.Left)).toEqual({ geometry: 'line', diff --git a/src/plots/dual-axes/adaptor.ts b/src/plots/dual-axes/adaptor.ts index 7cfc1ea659..344f155d1f 100644 --- a/src/plots/dual-axes/adaptor.ts +++ b/src/plots/dual-axes/adaptor.ts @@ -8,10 +8,10 @@ import { } from '../../adaptor/common'; import { percent } from '../../utils/transform/percent'; import { Params } from '../../core/adaptor'; +import { Datum } from '../../types'; import { flow, deepAssign } from '../../utils'; import { findViewById } from '../../utils/view'; -import { Datum } from '../../types'; -import { isColumn, getDefaultYAxis, getGeometryOption } from './util/option'; +import { isColumn, getYAxisWithDefault, getGeometryOption, getCompatibleYAxis } from './util/option'; import { getViewLegendItems } from './util/legend'; import { drawSingleGeometry } from './util/geometry'; import { DualAxesOptions, AxisType, DualAxesGeometry } from './types'; @@ -55,7 +55,7 @@ export function transformOptions(params: Params): Params): Params { // 左 View leftView.axis(xField, xAxis); - leftView.axis(yField[0], yAxis[yField[0]]); + leftView.axis(yField[0], getYAxisWithDefault(yAxis[yField[0]], AxisType.Left)); // 右 Y 轴 rightView.axis(xField, false); - rightView.axis(yField[1], yAxis[yField[1]]); + rightView.axis(yField[1], getYAxisWithDefault(yAxis[yField[1]], AxisType.Right)); return params; } diff --git a/src/plots/dual-axes/constant.ts b/src/plots/dual-axes/constant.ts index 3febf9f9dd..606baafc71 100644 --- a/src/plots/dual-axes/constant.ts +++ b/src/plots/dual-axes/constant.ts @@ -1,2 +1,21 @@ export const LEFT_AXES_VIEW = 'left-axes-view'; export const RIGHT_AXES_VIEW = 'right-axes-view'; + +export const DEFAULT_YAXIS_CONFIG = { + nice: true, + label: { + autoHide: true, + autoRotate: false, + }, +}; + +export const DEFAULT_LEFT_YAXIS_CONFIG = { + ...DEFAULT_YAXIS_CONFIG, + position: 'left', +}; + +export const DEFAULT_RIGHT_YAXIS_CONFIG = { + ...DEFAULT_YAXIS_CONFIG, + position: 'right', + grid: null, +}; diff --git a/src/plots/dual-axes/types.ts b/src/plots/dual-axes/types.ts index 0b1a3558f0..a0aec2b6d6 100644 --- a/src/plots/dual-axes/types.ts +++ b/src/plots/dual-axes/types.ts @@ -44,14 +44,27 @@ export type GeometryColumnOption = Pick< export type GeometryOption = GeometryColumnOption | GeometryLineOption; export type DualAxesOptions = Omit & { - // 通用数据配置 - /** 具体的数据 */ + /** + * 具体的数据,左右两边的数据 + */ readonly data: Array[]>; + /** + * 双轴图的 x 字段,x 字段名称需要保持一致 + */ readonly xField: string; + /** + * 双轴图左右 y 字段,需要不一致 + */ readonly yField: string[]; - readonly geometryOptions?: GeometryOption[]; + /** + * 左右两边的 yAxis 配置,使用 object 的方式,key 为 y 字段名,或者数组分别表示左右 + */ + readonly yAxis?: Options['yAxis'][] | Record; - readonly yAxis?: Record | Options['yAxis'][]; + /** + * 左右两边的图形配置 + */ + readonly geometryOptions?: GeometryOption[]; }; diff --git a/src/plots/dual-axes/util/option.ts b/src/plots/dual-axes/util/option.ts index 5825cb92ac..d23654a4ec 100644 --- a/src/plots/dual-axes/util/option.ts +++ b/src/plots/dual-axes/util/option.ts @@ -1,4 +1,5 @@ import { get, isArray } from '@antv/util'; +import { Axis } from '../../../types/axis'; import { deepAssign } from '../../../utils'; import { DualAxesOptions, @@ -8,6 +9,7 @@ import { GeometryColumnOption, AxisType, } from '../types'; +import { DEFAULT_LEFT_YAXIS_CONFIG, DEFAULT_RIGHT_YAXIS_CONFIG } from '../constant'; /** * 根据 GeometryOption 判断 geometry 是否为 line @@ -58,43 +60,35 @@ export function getGeometryOption( }; } -export function getDefaultYAxis( +/** + * 兼容 yAxis 为 arr 和 obj 的两种情况 + * @param yField + * @param yAxis + */ +export function getCompatibleYAxis( yField: DualAxesOptions['yField'], - yAxis: DualAxesOptions['yAxis'] + yAxis: Record | Axis[] ): DualAxesOptions['yAxis'] { - const DEFAULT_YAXIS_CONFIG = { - nice: true, - label: { - autoHide: true, - autoRotate: false, - }, - }; - - const DEFAULT_LEFT_YAXIS_CONFIG = { - ...DEFAULT_YAXIS_CONFIG, - position: 'left', - }; - - const DEFAULT_RIGHT_YAXIS_CONFIG = { - ...DEFAULT_YAXIS_CONFIG, - position: 'right', - grid: null, - }; - + const [y1, y2] = yField; if (isArray(yAxis)) { console.warn('yAxis should be object.'); - return { - [yField[0]]: yAxis[0] !== false ? deepAssign({}, DEFAULT_LEFT_YAXIS_CONFIG, yAxis[0]) : false, - [yField[1]]: yAxis[1] !== false ? deepAssign({}, DEFAULT_RIGHT_YAXIS_CONFIG, yAxis[1]) : false, - }; + return { [y1]: yAxis[0], [y2]: yAxis[1] }; } - return deepAssign( - {}, - { - [yField[0]]: DEFAULT_LEFT_YAXIS_CONFIG, - [yField[1]]: DEFAULT_RIGHT_YAXIS_CONFIG, - }, - yAxis - ); + // 追加默认值 + return deepAssign({ [y1]: undefined, [y2]: undefined }, yAxis); +} + +/** + * 获取默认值 + * @param yAxis + * @param axisType + */ +export function getYAxisWithDefault(yAxis: Axis, axisType: AxisType): Axis { + if (axisType === AxisType.Left) { + return yAxis === false ? false : deepAssign({}, DEFAULT_LEFT_YAXIS_CONFIG, yAxis); + } else if (axisType === AxisType.Right) { + return yAxis === false ? false : deepAssign({}, DEFAULT_RIGHT_YAXIS_CONFIG, yAxis); + } + return yAxis; }