From ff35bf60c120ce972378f40e3271db470471c846 Mon Sep 17 00:00:00 2001 From: yatbfm Date: Mon, 15 Sep 2025 23:01:38 +0800 Subject: [PATCH 1/5] feat: add prompt for heatmap --- .../src/transformers/heatmap.ts | 7 +++++- .../src/atom/chartGenerator/rule/index.ts | 24 ++++++++++++++++++- packages/vmind/src/atom/imageReader/prompt.ts | 3 ++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/generate-vchart/src/transformers/heatmap.ts b/packages/generate-vchart/src/transformers/heatmap.ts index def87a73..80742630 100644 --- a/packages/generate-vchart/src/transformers/heatmap.ts +++ b/packages/generate-vchart/src/transformers/heatmap.ts @@ -74,7 +74,12 @@ export const basicHeatMapAxes = (context: GenerateChartInput) => { } }, userConfig: { - type: 'band' + type: 'band', + label: { + style: { + angle: 90 + } + } }, filters: [axis => axis.orient === 'bottom', axis => axis.orient === 'top'] }, diff --git a/packages/vmind/src/atom/chartGenerator/rule/index.ts b/packages/vmind/src/atom/chartGenerator/rule/index.ts index b006c936..33b66eb4 100644 --- a/packages/vmind/src/atom/chartGenerator/rule/index.ts +++ b/packages/vmind/src/atom/chartGenerator/rule/index.ts @@ -89,6 +89,23 @@ const formatDataTable = (simpleVChartSpec: SimpleVChartSpec, data: DataTable) => finalData.reverse(); return finalData; } + // 热力图特殊处理 + else if (type === 'heatmap') { + // 拿到所有的'name',并设置值为1 + const finalData = Array.from( + new Set(data.map(item => item.name).concat(data.map(item => item.name1))) + .keys() + .map(key => ({ name: key, name1: key, value: 1 })) + ); + // 模型识别数据可能不全,尽可能补全数据 + for (const item of data) { + const obj = { name: item.name1, name1: item.name, value: item.value as number }; + if (finalData.findIndex(i => i.name === item.name && i.name1 === item.name1) === -1) { + finalData.push(item as typeof obj, obj); + } + } + return finalData; + } return data; }; @@ -171,8 +188,13 @@ export const getContextBySimpleVChartSpec = (simpleVChartSpec: SimpleVChartSpec) cell.x = 'value'; cell.y = 'value1'; } + if (chartType === 'heatmap') { + cell.x = 'name'; + cell.y = 'name1'; + cell.size = 'value'; + } - const fieldInfo = ['name', 'value', 'group', 'value1'].reduce((res, field) => { + const fieldInfo = ['name', 'value', 'group', 'value1', 'name1'].reduce((res, field) => { if (firstDatum && field in firstDatum) { res.push({ fieldName: field, diff --git a/packages/vmind/src/atom/imageReader/prompt.ts b/packages/vmind/src/atom/imageReader/prompt.ts index 06d430ca..a5694679 100644 --- a/packages/vmind/src/atom/imageReader/prompt.ts +++ b/packages/vmind/src/atom/imageReader/prompt.ts @@ -16,7 +16,8 @@ When executing the task, you need to meet the following requirements: 6. If all series in a composite chart are unidirectional bar charts, return the type as 'bar'; if the image is symmetrically distributed on both sides, must return the type as 'bidirectionalBar' 7. You should pay attention to distinguish radar chart and rose chart 8. If the type is treemap, the background color of each block needs to be used as the group value -9. For the type property of each element object in the axes field, it must be 'band' or 'linear' +9. If the type is heatmap, you need to return all correlation coefficient values, set the two dimensions of each correlation coefficient to 'name' and 'name1', with the value as 'value' +10. For the type property of each element object in the axes field, it must be 'band' or 'linear' # Answer \`\`\` From de2860a20490c27ee1cdefcab46acd103ae3586b Mon Sep 17 00:00:00 2001 From: yatbfm Date: Tue, 16 Sep 2025 21:46:27 +0800 Subject: [PATCH 2/5] feat: add prompt for linearProgress --- packages/vmind/src/atom/imageReader/prompt.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vmind/src/atom/imageReader/prompt.ts b/packages/vmind/src/atom/imageReader/prompt.ts index a5694679..8dd28f1b 100644 --- a/packages/vmind/src/atom/imageReader/prompt.ts +++ b/packages/vmind/src/atom/imageReader/prompt.ts @@ -18,6 +18,7 @@ When executing the task, you need to meet the following requirements: 8. If the type is treemap, the background color of each block needs to be used as the group value 9. If the type is heatmap, you need to return all correlation coefficient values, set the two dimensions of each correlation coefficient to 'name' and 'name1', with the value as 'value' 10. For the type property of each element object in the axes field, it must be 'band' or 'linear' +11. If the type is linearProgress, the metric value must be between 0 and 1 # Answer \`\`\` From a3c29d0e963fe0423396aef29cdc77611a3aa5ee Mon Sep 17 00:00:00 2001 From: yatbfm Date: Wed, 17 Sep 2025 12:15:44 +0800 Subject: [PATCH 3/5] feat: add pipeline for comparativeFunnel --- packages/generate-vchart/src/pipeline.ts | 4 +- .../src/transformers/comparativeFunnel.ts | 133 ++++++++++++++++++ .../generate-vchart/src/transformers/index.ts | 1 + .../src/atom/chartGenerator/rule/index.ts | 9 ++ .../vmind/src/atom/imageReader/interface.ts | 3 +- packages/vmind/src/atom/imageReader/prompt.ts | 3 +- 6 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 packages/generate-vchart/src/transformers/comparativeFunnel.ts diff --git a/packages/generate-vchart/src/pipeline.ts b/packages/generate-vchart/src/pipeline.ts index 80dea648..1565cd8a 100644 --- a/packages/generate-vchart/src/pipeline.ts +++ b/packages/generate-vchart/src/pipeline.ts @@ -30,6 +30,7 @@ const { pipelineWaterfall, pipelineWordCloud, pipelineBidirectionalBar, + pipelineComparativeFunnel, addSimpleComponents, theme } = allTransformers; @@ -70,7 +71,8 @@ const pipelineMap: { gauge: { type: 'gauge', aliasName: 'Gauge Chart', pipline: pipelineGauge }, heatmap: { type: 'heatmap', aliasName: 'Basic Heat Map', pipline: pipelineBasicHeatMap }, venn: { type: 'venn', aliasName: 'Venn Chart', pipline: pipelineVenn }, - bidirectionalBar: { type: 'common', aliasName: 'Bidirectional Bar Chart', pipline: pipelineBidirectionalBar } + bidirectionalBar: { type: 'common', aliasName: 'Bidirectional Bar Chart', pipline: pipelineBidirectionalBar }, + comparativeFunnel: { type: 'common', aliasName: 'Comparative Funnel Chart', pipline: pipelineComparativeFunnel } }; export const findPipelineByType = (type: string) => { diff --git a/packages/generate-vchart/src/transformers/comparativeFunnel.ts b/packages/generate-vchart/src/transformers/comparativeFunnel.ts new file mode 100644 index 00000000..01916385 --- /dev/null +++ b/packages/generate-vchart/src/transformers/comparativeFunnel.ts @@ -0,0 +1,133 @@ +import { array } from '@visactor/vutils'; +import { GenerateChartInput } from '../types'; +import { data, discreteLegend, formatXFields } from './common'; + +const title = (context: GenerateChartInput) => { + const { spec } = context; + const { title } = spec; + spec.title = { + ...title, + id: 'title' + }; + return { spec }; +}; + +const layout = (context: GenerateChartInput) => { + const { spec } = context; + spec.layout = { + type: 'grid', + col: 3, + row: 3, + colWidth: [{ index: 1, size: 120 }], + elements: [ + { modelId: 'title', col: 0, row: 0, colSpan: 3 }, + { modelId: 'legend', col: 0, row: 1, colSpan: 3 }, + { modelId: 'left', col: 0, row: 2 }, + { modelId: 'right', col: 2, row: 2 } + ] + }; + spec.region = [{ id: 'left' }, { id: 'right' }]; + return { spec }; +}; + +const comparativeFunnelSeries = (context: GenerateChartInput) => { + const { spec, dataTable, series, cell } = context; + const generateSeries = (index, align: 'left' | 'right') => { + return { + type: 'funnel', + dataIndex: index, + regionIndex: index, + isTransform: true, + gap: 2, + maxSize: '60%', + shape: 'rect', + funnelAlign: align, + categoryField: cell.x, + valueField: cell.y, + heightRatio: 1.5, + funnel: { + style: { + fill: { field: cell.category, scale: 'color' }, + cornerRadius: 4 + } + }, + transform: { + style: { + fill: { field: cell.category, scale: 'color' }, + fillOpacity: 0.1 + } + }, + outerLabel: { + visible: true, + line: { visible: false }, + formatMethod: (label, datum) => datum[array(cell.y)[0]], + style: { + fontSize: 24, + fontWeight: 'bold', + fill: 'black', + limit: Infinity + } + }, + extensionMark: [ + index === 0 + ? { + type: 'text', + dataIndex: 0, + style: { + text: data => data[array(cell.x)[0]], + fontSize: 24, + fill: 'grey', + textAlign: 'center', + x: (data, ctx) => { + const { vchart } = ctx; + return vchart.getCurrentSize().width / 2 - 10; + }, + y: (data, ctx) => { + const { getPoints } = ctx; + const [tl, tr, br, bl] = getPoints(data); + return (tl.y + bl.y) / 2; + } + } + } + : null + ].filter(Boolean) + }; + }; + spec.series = [generateSeries(0, 'right'), generateSeries(1, 'left')]; + return { spec }; +}; + +const comparativeFunnelLegend = (context: GenerateChartInput) => { + const { spec, cell } = context; + spec.seriesField = cell.category; + spec.legends = array(spec.legends).map(legend => ({ + ...legend, + id: 'legend', + orient: 'top' + })); + return { spec }; +}; + +const comparativeFunnelData = (context: GenerateChartInput) => { + const { spec, dataTable } = context; + const mp = {}; + dataTable.forEach(item => { + const { group } = item; + if (!mp[group]) { + mp[group] = []; + } + mp[group].push(item); + }); + spec.data = Object.entries(mp).map(([group, data]) => ({ id: group, values: data })); + return { spec }; +}; + +export const pipelineComparativeFunnel = [ + title, + formatXFields, + layout, + comparativeFunnelData, + comparativeFunnelSeries, + discreteLegend, + comparativeFunnelLegend +]; diff --git a/packages/generate-vchart/src/transformers/index.ts b/packages/generate-vchart/src/transformers/index.ts index 19b2a14f..8223a806 100644 --- a/packages/generate-vchart/src/transformers/index.ts +++ b/packages/generate-vchart/src/transformers/index.ts @@ -29,3 +29,4 @@ export * from './waterfall'; export * from './wordcloud'; export * from './bidirectionalBar'; +export * from './comparativeFunnel'; diff --git a/packages/vmind/src/atom/chartGenerator/rule/index.ts b/packages/vmind/src/atom/chartGenerator/rule/index.ts index 33b66eb4..0e85a1dc 100644 --- a/packages/vmind/src/atom/chartGenerator/rule/index.ts +++ b/packages/vmind/src/atom/chartGenerator/rule/index.ts @@ -118,6 +118,10 @@ export const getContextBySimpleVChartSpec = (simpleVChartSpec: SimpleVChartSpec) simpleVChartSpec, data ?? originalSeries?.reduce((acc, cur) => { + // 对比漏斗图,group字段可能不会在data中,特殊处理 + if (type === 'comparativeFunnel' && 'group' in cur) { + cur.data?.forEach(item => (item.group = cur.group as string)); + } acc.push(...cur.data); return acc; }, []) @@ -193,6 +197,11 @@ export const getContextBySimpleVChartSpec = (simpleVChartSpec: SimpleVChartSpec) cell.y = 'name1'; cell.size = 'value'; } + if (chartType === 'comparativeFunnel') { + cell.x = 'name'; + cell.y = 'value'; + cell.category = 'group'; + } const fieldInfo = ['name', 'value', 'group', 'value1', 'name1'].reduce((res, field) => { if (firstDatum && field in firstDatum) { diff --git a/packages/vmind/src/atom/imageReader/interface.ts b/packages/vmind/src/atom/imageReader/interface.ts index 9a388193..d30cef66 100644 --- a/packages/vmind/src/atom/imageReader/interface.ts +++ b/packages/vmind/src/atom/imageReader/interface.ts @@ -30,7 +30,8 @@ export interface SimpleVChartSpec { | 'liquid' | 'venn' | 'mosaic' - | 'bidirectionalBar'; + | 'bidirectionalBar' + | 'comparativeFunnel'; /** * "none" - 无坐标系 * "rect" - 直角坐标系 diff --git a/packages/vmind/src/atom/imageReader/prompt.ts b/packages/vmind/src/atom/imageReader/prompt.ts index 8dd28f1b..74d83d5f 100644 --- a/packages/vmind/src/atom/imageReader/prompt.ts +++ b/packages/vmind/src/atom/imageReader/prompt.ts @@ -19,12 +19,13 @@ When executing the task, you need to meet the following requirements: 9. If the type is heatmap, you need to return all correlation coefficient values, set the two dimensions of each correlation coefficient to 'name' and 'name1', with the value as 'value' 10. For the type property of each element object in the axes field, it must be 'band' or 'linear' 11. If the type is linearProgress, the metric value must be between 0 and 1 +12. If the type is 'funnel' and consists of two funnel charts, return the type as 'comparativeFunnel' # Answer \`\`\` { /** 图表的类型 */ - type: "common"|"area"|"line"|"bar"|"rangeColumn"|"rangeArea"|"map"|"pie"|"radar"|"rose"|"scatter"|"sequence"|"circularProgress"|"linearProgress"|"wordCloud"|"funnel"|"waterfall"|"boxPlot"|"gauge"|"sankey"|"treemap"|"sunburst"|"circlePacking"|"heatmap"|"liquid"|"venn"|"mosaic"|"bidirectionalBar"; + type: "common"|"area"|"line"|"bar"|"rangeColumn"|"rangeArea"|"map"|"pie"|"radar"|"rose"|"scatter"|"sequence"|"circularProgress"|"linearProgress"|"wordCloud"|"funnel"|"waterfall"|"boxPlot"|"gauge"|"sankey"|"treemap"|"sunburst"|"circlePacking"|"heatmap"|"liquid"|"venn"|"mosaic"|"bidirectionalBar"|"comparativeFunnel"; /** * "none" - 无坐标系 * "rect" - 直角坐标系 From 818c5e4fde40fe0a79df0e46954b947c5af4c2fe Mon Sep 17 00:00:00 2001 From: yatbfm Date: Wed, 17 Sep 2025 12:41:14 +0800 Subject: [PATCH 4/5] feat: add test unit and comment --- .../transformers/comparativeFunnel.test.ts | 167 ++++++++++++++++++ .../src/atom/chartGenerator/rule/index.ts | 1 + 2 files changed, 168 insertions(+) create mode 100644 packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts diff --git a/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts b/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts new file mode 100644 index 00000000..6eab647f --- /dev/null +++ b/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts @@ -0,0 +1,167 @@ +import { generateChart } from '../../src'; + +const MOCK_DATA_TABLE = [ + { group: 'A', name: 'Category1', value: 10 }, + { group: 'A', name: 'Category2', value: 15 }, + { group: 'B', name: 'Category1', value: 20 }, + { group: 'B', name: 'Category2', value: 25 } +]; + +const layout = { + type: 'grid', + col: 3, + row: 3, + colWidth: [ + { + index: 1, + size: 120 + } + ], + elements: [ + { + modelId: 'title', + col: 0, + row: 0, + colSpan: 3 + }, + { + modelId: 'legend', + col: 0, + row: 1, + colSpan: 3 + }, + { + modelId: 'left', + col: 0, + row: 2 + }, + { + modelId: 'right', + col: 2, + row: 2 + } + ] +}; + +const region = [ + { + id: 'left' + }, + { + id: 'right' + } +]; + +describe('generate comparative funnel chart', () => { + it('should generate comparative funnel chart with dataTable', () => { + const { spec } = generateChart('comparativeFunnel', { + dataTable: MOCK_DATA_TABLE, + cell: { + x: 'name', + y: 'value', + category: 'group' + }, + spec: {} + }); + expect(spec.type).toBe('common'); + expect(spec.layout).toEqual(layout); + expect(spec.region).toEqual(region); + expect(spec.data).toEqual( + Object.entries( + MOCK_DATA_TABLE.reduce((acc, curr) => { + if (!acc[curr.group]) { + acc[curr.group] = []; + } + acc[curr.group].push(curr); + return acc; + }, {} as any) + ).map(([group, data]) => ({ + id: group, + values: data + })) + ); + expect(spec.series).toEqual([ + { + type: 'funnel', + dataIndex: 0, + regionIndex: 0, + isTransform: true, + gap: 2, + maxSize: '60%', + shape: 'rect', + funnelAlign: 'right', + categoryField: 'name', + valueField: 'value', + heightRatio: 1.5, + funnel: { + style: { + fill: { field: 'group', scale: 'color' }, + cornerRadius: 4 + } + }, + transform: { + style: { + fill: { field: 'group', scale: 'color' }, + fillOpacity: 0.1 + } + }, + outerLabel: { + visible: true, + line: { visible: false }, + style: { + fontSize: 24, + fontWeight: 'bold', + fill: 'black', + limit: Infinity + } + }, + extensionMark: [ + { + type: 'text', + dataIndex: 0, + style: { + fontSize: 24, + fill: 'grey', + textAlign: 'center' + } + } + ] + }, + { + type: 'funnel', + dataIndex: 1, + regionIndex: 1, + isTransform: true, + gap: 2, + maxSize: '60%', + shape: 'rect', + funnelAlign: 'left', + categoryField: 'name', + valueField: 'value', + heightRatio: 1.5, + funnel: { + style: { + fill: { field: 'group', scale: 'color' }, + cornerRadius: 4 + } + }, + transform: { + style: { + fill: { field: 'group', scale: 'color' }, + fillOpacity: 0.1 + } + }, + outerLabel: { + visible: true, + line: { visible: false }, + style: { + fontSize: 24, + fontWeight: 'bold', + fill: 'black', + limit: Infinity + } + } + } + ]); + }); +}); diff --git a/packages/vmind/src/atom/chartGenerator/rule/index.ts b/packages/vmind/src/atom/chartGenerator/rule/index.ts index 0e85a1dc..1ba9073e 100644 --- a/packages/vmind/src/atom/chartGenerator/rule/index.ts +++ b/packages/vmind/src/atom/chartGenerator/rule/index.ts @@ -194,6 +194,7 @@ export const getContextBySimpleVChartSpec = (simpleVChartSpec: SimpleVChartSpec) } if (chartType === 'heatmap') { cell.x = 'name'; + // 热图有两个维度数据,因此新增name1字段 cell.y = 'name1'; cell.size = 'value'; } From 6a12f046e4b2c99a4152ee360eb7a077f5e0ae9d Mon Sep 17 00:00:00 2001 From: yatbfm Date: Wed, 17 Sep 2025 13:24:13 +0800 Subject: [PATCH 5/5] feat: fix test unit --- .../transformers/comparativeFunnel.test.ts | 160 +++++++++--------- .../__tests__/transformers/heatmap.test.ts | 10 ++ .../src/transformers/comparativeFunnel.ts | 14 +- 3 files changed, 99 insertions(+), 85 deletions(-) diff --git a/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts b/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts index 6eab647f..e57b0ebc 100644 --- a/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts +++ b/packages/generate-vchart/__tests__/transformers/comparativeFunnel.test.ts @@ -80,88 +80,92 @@ describe('generate comparative funnel chart', () => { values: data })) ); - expect(spec.series).toEqual([ - { - type: 'funnel', - dataIndex: 0, - regionIndex: 0, - isTransform: true, - gap: 2, - maxSize: '60%', - shape: 'rect', - funnelAlign: 'right', - categoryField: 'name', - valueField: 'value', - heightRatio: 1.5, - funnel: { - style: { - fill: { field: 'group', scale: 'color' }, - cornerRadius: 4 - } - }, - transform: { - style: { - fill: { field: 'group', scale: 'color' }, - fillOpacity: 0.1 - } - }, - outerLabel: { - visible: true, - line: { visible: false }, - style: { - fontSize: 24, - fontWeight: 'bold', - fill: 'black', - limit: Infinity - } - }, - extensionMark: [ - { - type: 'text', - dataIndex: 0, + const serialize = (obj: any) => JSON.parse(JSON.stringify(obj)); + expect(serialize(spec.series)).toEqual( + serialize([ + { + type: 'funnel', + dataIndex: 0, + regionIndex: 0, + isTransform: true, + gap: 2, + maxSize: '60%', + shape: 'rect', + funnelAlign: 'right', + categoryField: 'name', + valueField: 'value', + heightRatio: 1.5, + funnel: { + style: { + fill: { field: 'group', scale: 'color' }, + cornerRadius: 4 + } + }, + transform: { + style: { + fill: { field: 'group', scale: 'color' }, + fillOpacity: 0.1 + } + }, + outerLabel: { + visible: true, + line: { visible: false }, style: { fontSize: 24, - fill: 'grey', - textAlign: 'center' + fontWeight: 'bold', + fill: 'black', + limit: Infinity } - } - ] - }, - { - type: 'funnel', - dataIndex: 1, - regionIndex: 1, - isTransform: true, - gap: 2, - maxSize: '60%', - shape: 'rect', - funnelAlign: 'left', - categoryField: 'name', - valueField: 'value', - heightRatio: 1.5, - funnel: { - style: { - fill: { field: 'group', scale: 'color' }, - cornerRadius: 4 - } - }, - transform: { - style: { - fill: { field: 'group', scale: 'color' }, - fillOpacity: 0.1 - } + }, + extensionMark: [ + { + type: 'text', + dataIndex: 0, + style: { + fontSize: 24, + fill: 'grey', + textAlign: 'center' + } + } + ] }, - outerLabel: { - visible: true, - line: { visible: false }, - style: { - fontSize: 24, - fontWeight: 'bold', - fill: 'black', - limit: Infinity - } + { + type: 'funnel', + dataIndex: 1, + regionIndex: 1, + isTransform: true, + gap: 2, + maxSize: '60%', + shape: 'rect', + funnelAlign: 'left', + categoryField: 'name', + valueField: 'value', + heightRatio: 1.5, + funnel: { + style: { + fill: { field: 'group', scale: 'color' }, + cornerRadius: 4 + } + }, + transform: { + style: { + fill: { field: 'group', scale: 'color' }, + fillOpacity: 0.1 + } + }, + outerLabel: { + visible: true, + line: { visible: false }, + style: { + fontSize: 24, + fontWeight: 'bold', + fill: 'black', + limit: Infinity + } + }, + extensionMark: [] } - } - ]); + ]) + ); }); }); diff --git a/packages/generate-vchart/__tests__/transformers/heatmap.test.ts b/packages/generate-vchart/__tests__/transformers/heatmap.test.ts index ecf9578a..c7fcc233 100644 --- a/packages/generate-vchart/__tests__/transformers/heatmap.test.ts +++ b/packages/generate-vchart/__tests__/transformers/heatmap.test.ts @@ -48,6 +48,11 @@ describe('generateChart', () => { grid: { visible: false }, + label: { + style: { + angle: 90 + } + }, domainLine: { visible: false } @@ -261,6 +266,11 @@ describe('generateChart', () => { grid: { visible: false }, + label: { + style: { + angle: 90 + } + }, domainLine: { visible: false }, diff --git a/packages/generate-vchart/src/transformers/comparativeFunnel.ts b/packages/generate-vchart/src/transformers/comparativeFunnel.ts index 01916385..2886de73 100644 --- a/packages/generate-vchart/src/transformers/comparativeFunnel.ts +++ b/packages/generate-vchart/src/transformers/comparativeFunnel.ts @@ -1,5 +1,5 @@ import { array } from '@visactor/vutils'; -import { GenerateChartInput } from '../types'; +import { DataItem, GenerateChartInput } from '../types'; import { data, discreteLegend, formatXFields } from './common'; const title = (context: GenerateChartInput) => { @@ -31,8 +31,8 @@ const layout = (context: GenerateChartInput) => { }; const comparativeFunnelSeries = (context: GenerateChartInput) => { - const { spec, dataTable, series, cell } = context; - const generateSeries = (index, align: 'left' | 'right') => { + const { spec, cell } = context; + const generateSeries = (index: number, align: 'left' | 'right') => { return { type: 'funnel', dataIndex: index, @@ -60,7 +60,7 @@ const comparativeFunnelSeries = (context: GenerateChartInput) => { outerLabel: { visible: true, line: { visible: false }, - formatMethod: (label, datum) => datum[array(cell.y)[0]], + formatMethod: (data: any, datum: DataItem) => datum[array(cell.y)[0]], style: { fontSize: 24, fontWeight: 'bold', @@ -74,15 +74,15 @@ const comparativeFunnelSeries = (context: GenerateChartInput) => { type: 'text', dataIndex: 0, style: { - text: data => data[array(cell.x)[0]], + text: (data: any) => data[array(cell.x)[0]], fontSize: 24, fill: 'grey', textAlign: 'center', - x: (data, ctx) => { + x: (data: any, ctx: any) => { const { vchart } = ctx; return vchart.getCurrentSize().width / 2 - 10; }, - y: (data, ctx) => { + y: (data: DataItem, ctx: any) => { const { getPoints } = ctx; const [tl, tr, br, bl] = getPoints(data); return (tl.y + bl.y) / 2;