diff --git a/src/DualAxes/demos/common.tsx b/src/DualAxes/demos/common.tsx index cc0713e..46853b0 100644 --- a/src/DualAxes/demos/common.tsx +++ b/src/DualAxes/demos/common.tsx @@ -1,82 +1,62 @@ +import type { DualAxesProps } from '@antv/gpt-vis'; import { DualAxes } from '@antv/gpt-vis'; import React from 'react'; -const children = [ - { - type: 'column', - data: [ - { category: '2020-08-20', consumeTime: 10868 }, - { category: '2020-08-21', consumeTime: 8786 }, - { category: '2020-08-22', consumeTime: 10824 }, - { category: '2020-08-23', consumeTime: 7860 }, - { category: '2020-08-24', consumeTime: 13253 }, - { category: '2020-08-25', consumeTime: 17015 }, - { category: '2020-08-26', consumeTime: 19298 }, - { category: '2020-08-27', consumeTime: 13937 }, - { category: '2020-08-28', consumeTime: 11541 }, - { category: '2020-08-29', consumeTime: 15244 }, - { category: '2020-08-30', consumeTime: 14247 }, - { category: '2020-08-31', consumeTime: 9402 }, - { category: '2020-09-01', consumeTime: 10440 }, - { category: '2020-09-02', consumeTime: 9345 }, - { category: '2020-09-03', consumeTime: 18459 }, - { category: '2020-09-04', consumeTime: 9763 }, - { category: '2020-09-05', consumeTime: 11074 }, - { category: '2020-09-06', consumeTime: 11770 }, - { category: '2020-09-07', consumeTime: 12206 }, - { category: '2020-09-08', consumeTime: 11434 }, - { category: '2020-09-09', consumeTime: 16218 }, - { category: '2020-09-10', consumeTime: 11914 }, - { category: '2020-09-11', consumeTime: 16781 }, - { category: '2020-09-12', consumeTime: 10555 }, - { category: '2020-09-13', consumeTime: 10899 }, - { category: '2020-09-14', consumeTime: 10713 }, - { category: '2020-09-15', consumeTime: 0 }, - { category: '2020-09-16', consumeTime: 0 }, - { category: '2020-09-17', consumeTime: 20357 }, - { category: '2020-09-18', consumeTime: 10424 }, - ], - yField: 'consumeTime', - style: { maxWidth: 80 }, - }, - { - type: 'line', - data: [ - { time: '2020-08-20', completeTime: 649.483 }, - { time: '2020-08-21', completeTime: 1053.7 }, - { time: '2020-08-22', completeTime: 679.817 }, - { time: '2020-08-23', completeTime: 638.117 }, - { time: '2020-08-24', completeTime: 843.3 }, - { time: '2020-08-25', completeTime: 1092.983 }, - { time: '2020-08-26', completeTime: 1036.317 }, - { time: '2020-08-27', completeTime: 1031.9 }, - { time: '2020-08-28', completeTime: 803.467 }, - { time: '2020-08-29', completeTime: 830.733 }, - { time: '2020-08-30', completeTime: 709.867 }, - { time: '2020-08-31', completeTime: 665.233 }, - { time: '2020-09-01', completeTime: 696.367 }, - { time: '2020-09-02', completeTime: 692.867 }, - { time: '2020-09-03', completeTime: 936.017 }, - { time: '2020-09-04', completeTime: 782.867 }, - { time: '2020-09-05', completeTime: 653.8 }, - { time: '2020-09-06', completeTime: 856.683 }, - { time: '2020-09-07', completeTime: 777.15 }, - { time: '2020-09-08', completeTime: 773.283 }, - { time: '2020-09-09', completeTime: 833.3 }, - { time: '2020-09-10', completeTime: 793.517 }, - { time: '2020-09-11', completeTime: 894.45 }, - { time: '2020-09-12', completeTime: 725.55 }, - { time: '2020-09-13', completeTime: 709.967 }, - { time: '2020-09-14', completeTime: 787.6 }, - { time: '2020-09-15', completeTime: 644.183 }, - { time: '2020-09-16', completeTime: 1066.65 }, - { time: '2020-09-17', completeTime: 932.45 }, - { time: '2020-09-18', completeTime: 753.583 }, - ], - yField: 'completeTime', - }, -]; +const config: DualAxesProps = { + categories: [ + '2020-08-20', + '2020-08-21', + '2020-08-22', + '2020-08-23', + '2020-08-24', + '2020-08-25', + '2020-08-26', + '2020-08-27', + '2020-08-28', + '2020-08-29', + '2020-08-30', + '2020-08-31', + '2020-09-01', + '2020-09-02', + '2020-09-03', + '2020-09-04', + '2020-09-05', + '2020-09-06', + '2020-09-07', + '2020-09-08', + '2020-09-09', + '2020-09-10', + '2020-09-11', + '2020-09-12', + '2020-09-13', + '2020-09-14', + '2020-09-15', + '2020-09-16', + '2020-09-17', + '2020-09-18', + ], + series: [ + { + type: 'column', + data: [ + 10868, 8786, 10824, 7860, 13253, 17015, 19298, 13937, 11541, 15244, 14247, 9402, 10440, + 9345, 18459, 9763, 11074, 11770, 12206, 11434, 16218, 11914, 16781, 10555, 10899, 10713, 0, + 0, 20357, 10424, + ], + axisYTitle: '消耗时间', + }, + { + type: 'line', + data: [ + 649.483, 1053.7, 679.817, 638.117, 843.3, 1092.983, 1036.317, 1031.9, 803.467, 830.733, + 709.867, 665.233, 696.367, 692.867, 936.017, 782.867, 653.8, 856.683, 777.15, 773.283, + 833.3, 793.517, 894.45, 725.55, 709.967, 787.6, 644.183, 1066.65, 932.45, 753.583, + ], + axisYTitle: '完成时间', + }, + ], +}; export default () => { - return ; + return ; }; diff --git a/src/DualAxes/demos/markdown.tsx b/src/DualAxes/demos/markdown.tsx index abcc787..fc346ae 100644 --- a/src/DualAxes/demos/markdown.tsx +++ b/src/DualAxes/demos/markdown.tsx @@ -8,22 +8,17 @@ const markdownContent = ` \`\`\`vis-chart { "type": "dual-axes", - "children": [ + "categories": ["2020", "2021", "2022"], + "series": [ { "type": "column", - "data": [ - { "category": "2020", "value": 500 }, - { "category": "2021", "value": 600 }, - { "category": "2022", "value": 700 } - ] + "data": [500, 600, 700], + "axisYTitle": "amount" }, { "type": "line", - "data": [ - { "time": "2020", "value": 10 }, - { "time": "2021", "value": 12 }, - { "time": "2022", "value": 15 } - ] + "data": [10, 12, 15], + "axisYTitle": "rate" } ] } diff --git a/src/DualAxes/demos/multiple.tsx b/src/DualAxes/demos/multiple.tsx index 5acb90a..56ad3a0 100644 --- a/src/DualAxes/demos/multiple.tsx +++ b/src/DualAxes/demos/multiple.tsx @@ -7,172 +7,77 @@ const markdownContent = ` \`\`\`vis-chart { - "type": "dual-axes", - "xField": "Month", - "children": [ - { - "type": "column", - "yField": "Evaporation", - "data": [ - { - "Month": "Jan", - "Evaporation": 2 - }, - { - "Month": "Feb", - "Evaporation": 4.9 - }, - { - "Month": "Mar", - "Evaporation": 7 - }, - { - "Month": "Apr", - "Evaporation": 23.2 - }, - { - "Month": "May", - "Evaporation": 25.6 - }, - { - "Month": "Jun", - "Evaporation": 76.7 - }, - { - "Month": "Jul", - "Evaporation": 135.6 - }, - { - "Month": "Aug", - "Evaporation": 162.2 - }, - { - "Month": "Sep", - "Evaporation": 32.6 - }, - { - "Month": "Oct", - "Evaporation": 20 - }, - { - "Month": "Nov", - "Evaporation": 6.4 - }, - { - "Month": "Dec", - "Evaporation": 3.3 - } - ] - }, - { - "type": "line", - "yField": "Precipitation", - "data": [ - { - "Month": "Jan", - "Precipitation": 2.6 - }, - { - "Month": "Feb", - "Precipitation": 5.9 - }, - { - "Month": "Mar", - "Precipitation": 9 - }, - { - "Month": "Apr", - "Precipitation": 26.4 - }, - { - "Month": "May", - "Precipitation": 28.7 - }, - { - "Month": "Jun", - "Precipitation": 70.7 - }, - { - "Month": "Jul", - "Precipitation": 175.6 - }, - { - "Month": "Aug", - "Precipitation": 182.2 - }, - { - "Month": "Sep", - "Precipitation": 48.7 - }, - { - "Month": "Oct", - "Precipitation": 18.8 - }, - { - "Month": "Nov", - "Precipitation": 6 - }, - { - "Month": "Dec", - "Precipitation": 2.3 - } - ] - }, - { - "type": "line", - "yField": "Temperature", - "data": [ - { - "Month": "Jan", - "Temperature": 2 - }, - { - "Month": "Feb", - "Temperature": 2.2 - }, - { - "Month": "Mar", - "Temperature": 3.3 - }, - { - "Month": "Apr", - "Temperature": 4.5 - }, - { - "Month": "May", - "Temperature": 6.3 - }, - { - "Month": "Jun", - "Temperature": 10.2 - }, - { - "Month": "Jul", - "Temperature": 20.3 - }, - { - "Month": "Aug", - "Temperature": 23.4 - }, - { - "Month": "Sep", - "Temperature": 23 - }, - { - "Month": "Oct", - "Temperature": 16.5 - }, - { - "Month": "Nov", - "Temperature": 12 - }, - { - "Month": "Dec", - "Temperature": 6.2 - } - ] - } - ] + "type": "dual-axes", + "categories": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ], + "series": [ + { + "type": "column", + "data": [ + 26, + 59, + 90, + 264, + 287, + 707, + 1756, + 1822, + 487, + 188, + 60, + 23 + ], + "axisYTitle": "总体增长量" + }, + { + "type": "line", + "data": [ + 2.6, + 5.9, + 9, + 26.4, + 28.7, + 70.7, + 175.6, + 182.2, + 48.7, + 18.8, + 6, + 2.3 + ], + "axisYTitle": "A增长率" + }, + { + "type": "line", + "data": [ + 2, + 2.2, + 3.3, + 4.5, + 6.3, + 10.2, + 20.3, + 23.4, + 23, + 16.5, + 12, + 6.2 + ], + "axisYTitle": "B增长率" + } + ] } \`\`\` `; diff --git a/src/DualAxes/index.md b/src/DualAxes/index.md index 767f20e..81a311f 100644 --- a/src/DualAxes/index.md +++ b/src/DualAxes/index.md @@ -13,33 +13,26 @@ demo: { cols: 2 } 单独使用 使用 Markdown 协议 -多轴图 +多轴图 ## Spec ```json { "type": "dual-axes", - "children": [ + "categories": ["2018", "2019", "2020", "2021", "2022"], + "title": "2018-2022销售额与利润率", + "axisXTitle": "年份", + "series": [ { "type": "column", - "data": [ - { "category": "2018", "value": 91.9 }, - { "category": "2019", "value": 99.1 }, - { "category": "2020", "value": 101.6 }, - { "category": "2021", "value": 114.4 }, - { "category": "2022", "value": 121 } - ] + "data": [91.9, 99.1, 101.6, 114.4, 121], + "axisYTitle": "销售额" }, { "type": "line", - "data": [ - { "time": "2018", "value": 0.055 }, - { "time": "2019", "value": 0.06 }, - { "time": "2020", "value": 0.062 }, - { "time": "2021", "value": 0.07 }, - { "time": "2022", "value": 0.075 } - ] + "data": [0.055, 0.06, 0.062, 0.07, 0.075], + "axisYTitle": "利润率" } ] } @@ -49,8 +42,18 @@ demo: { cols: 2 } ### DualAxesProps -| 属性 | 类型 | 是否必传 | 默认值 | 说明 | -| -------- | ---------------------------- | -------- | ------ | -------------------------------------------------------------------------------------------------- | -| children | (ColumnProps \| LineProps)[] | 是 | - | 图表详细组合,可以是不同图表的组合,需要确保 data 的 x 相同 | -| title | string | 否 | - | 图表的标题 | -| ... | - | - | - | 更多属性,详见 [Ant Design Charts ](https://ant-design-charts.antgroup.com/options/plots/overview) | +| 属性 | 类型 | 是否必传 | 默认值 | 说明 | +| ---------- | ---------------- | -------- | ------ | -------------------------------------------------------------------------------------------------- | +| categories | string[] | 是 | - | x 轴对应的数据 | +| series | SeriesDataItem[] | 是 | - | 子图的数据 | +| title | string | 否 | - | 图表的标题 | +| axisXTitle | string | 否 | - | x 轴的标题 | +| ... | - | - | - | 更多属性,详见 [Ant Design Charts ](https://ant-design-charts.antgroup.com/options/plots/overview) | + +### SeriesDataItem + +| 属性 | 类型 | 是否必传 | 默认值 | 说明 | +| ---------- | -------- | -------- | ------ | ---------- | +| type | string | 是 | - | 子图的类型 | +| data | number[] | 是 | - | 子图的数据 | +| axisYTitle | string | 否 | - | y 轴的标题 | diff --git a/src/DualAxes/index.tsx b/src/DualAxes/index.tsx index f85d5a2..8d9a45f 100644 --- a/src/DualAxes/index.tsx +++ b/src/DualAxes/index.tsx @@ -1,26 +1,49 @@ import type { DualAxesConfig } from '@ant-design/plots'; import { DualAxes as ADCDualAxes } from '@ant-design/plots'; import React, { useMemo } from 'react'; -import type { ColumnDataItem } from '../Column'; import { usePlotConfig } from '../ConfigProvider/hooks'; -import type { LineDataItem } from '../Line'; import { transform } from './util'; -export type DualAxesProps = Partial; +export type DualAxesProps = Partial & { + categories: string[]; + axisXTitle?: string; + series: DualAxesSeriesItem[]; + legendTypeList: string[]; +}; -export type DualAxesDataItem = ColumnDataItem | LineDataItem; +export type DualAxesSeriesItem = { + type: string; + data: number[]; + axisYTitle?: string; +}; -const defaultConfig = (props: DualAxesConfig): DualAxesConfig => { - const { xField = 'time' } = props; +const defaultConfig = (props: DualAxesProps): DualAxesConfig => { + const { xField = 'category', axisXTitle, legendTypeList } = props; return { xField, - legend: {}, + axis: { + x: { + title: axisXTitle, + }, + }, + legend: { + color: { + itemMarker: (v: string, i: number) => { + return legendTypeList[i]; + }, + }, + }, + scale: { + color: { + palette: 'category10', + }, + }, }; }; const DualAxes = (props: DualAxesProps) => { - const { children, xField, ...others } = props; - const transformData = useMemo(() => transform(children, xField as string), [children]); + const { categories, series, ...others } = props; + const transformData = useMemo(() => transform(series, categories), [props]); const config = usePlotConfig('DualAxes', defaultConfig, { ...others, ...transformData, diff --git a/src/DualAxes/util.ts b/src/DualAxes/util.ts index 37149f1..e7646d7 100644 --- a/src/DualAxes/util.ts +++ b/src/DualAxes/util.ts @@ -1,64 +1,15 @@ -import type { DualAxesDataItem } from '.'; +import type { DualAxesSeriesItem } from '.'; import { ChartType } from '../types'; -type DatasetItem = { - data: DualAxesDataItem[]; - yField: string; -}; +export function transform(series: DualAxesSeriesItem[], categories: string[]) { + const newChildren = series.map((item: any, index: number) => { + const { type, axisYTitle, ...others } = item; -/** - * Merges data for dual-axes charts. - * @param children - The children containing chart data. - * @param xField - The field used as x-axis, defaults to 'time'. - * @returns Merged global data. - */ -function mergeData(children: any[], xField: string = 'time'): any[] { - const originalData = children.map((child) => { - return { - data: child.data, - yField: child.yField, - }; - }); - const mergedData: { [key: string]: any }[] = []; - const xFieldMap: Record> = {}; - - originalData.forEach((dataset, index) => { - const { data, yField }: DatasetItem = dataset; - data.forEach((entry) => { - const key = entry[xField] ?? entry.category; - if (!key) return; - - if (!xFieldMap[key]) { - xFieldMap[key] = {}; - } - - if (entry.value !== undefined) { - xFieldMap[key][`value_${index + 1}`] = entry.value; - } else { - xFieldMap[key][yField] = entry[yField] as number; - } - }); - }); - - for (const xFieldKey in xFieldMap) { - if (Object.keys(xFieldMap[xFieldKey]).length === originalData.length) { - mergedData.push({ [xField]: xFieldKey, ...xFieldMap[xFieldKey] }); - } - } - - return mergedData; -} - -export function transform(children: any, xField: string = 'time') { - const newChildren = children.map((item: any, index: number) => { - const { type, style, axis, yField, ...others } = item; - - const defaultYField = `value_${index + 1}`; + const defaultYField = axisYTitle || `value_${index + 1}`; const baseConfig = { ...others, - yField: yField || defaultYField, - style, - axis, + yField: defaultYField, + axis: { y: { title: axisYTitle } }, // data放在最外层 data: undefined, }; @@ -72,17 +23,35 @@ export function transform(children: any, xField: string = 'time') { ...baseConfig, type, shapeField: 'smooth', - axis: { y: { position: 'right' }, ...axis }, - style: { lineWidth: 2, ...style }, + axis: { y: { position: 'right', title: axisYTitle } }, + style: { lineWidth: 2 }, }; } return baseConfig; }); + const newData = categories.map((item: string, index: number) => { + const temp = { + category: item, + } as { + category: string; + [key: string]: any; + }; + series.forEach((s: DualAxesSeriesItem, i: number) => { + const defaultYField = s.axisYTitle || `value_${i + 1}`; + temp[defaultYField] = s.data[index]; + }); + return temp; + }); + + const legendTypeList = series.map((item: any) => { + return item.type === ChartType.Line ? 'smooth' : 'rect'; + }); + return { children: newChildren, - data: mergeData(children, xField), - xField, + data: newData, + legendTypeList, }; }