|
| 1 | +import { array } from '@visactor/vutils'; |
| 2 | +import { DataItem, GenerateChartInput } from '../types'; |
| 3 | +import { data, discreteLegend, formatXFields } from './common'; |
| 4 | + |
| 5 | +const title = (context: GenerateChartInput) => { |
| 6 | + const { spec } = context; |
| 7 | + const { title } = spec; |
| 8 | + spec.title = { |
| 9 | + ...title, |
| 10 | + id: 'title' |
| 11 | + }; |
| 12 | + return { spec }; |
| 13 | +}; |
| 14 | + |
| 15 | +const layout = (context: GenerateChartInput) => { |
| 16 | + const { spec } = context; |
| 17 | + spec.layout = { |
| 18 | + type: 'grid', |
| 19 | + col: 3, |
| 20 | + row: 3, |
| 21 | + colWidth: [{ index: 1, size: 120 }], |
| 22 | + elements: [ |
| 23 | + { modelId: 'title', col: 0, row: 0, colSpan: 3 }, |
| 24 | + { modelId: 'legend', col: 0, row: 1, colSpan: 3 }, |
| 25 | + { modelId: 'left', col: 0, row: 2 }, |
| 26 | + { modelId: 'right', col: 2, row: 2 } |
| 27 | + ] |
| 28 | + }; |
| 29 | + spec.region = [{ id: 'left' }, { id: 'right' }]; |
| 30 | + return { spec }; |
| 31 | +}; |
| 32 | + |
| 33 | +const comparativeFunnelSeries = (context: GenerateChartInput) => { |
| 34 | + const { spec, cell } = context; |
| 35 | + const generateSeries = (index: number, align: 'left' | 'right') => { |
| 36 | + return { |
| 37 | + type: 'funnel', |
| 38 | + dataIndex: index, |
| 39 | + regionIndex: index, |
| 40 | + isTransform: true, |
| 41 | + gap: 2, |
| 42 | + maxSize: '60%', |
| 43 | + shape: 'rect', |
| 44 | + funnelAlign: align, |
| 45 | + categoryField: cell.x, |
| 46 | + valueField: cell.y, |
| 47 | + heightRatio: 1.5, |
| 48 | + funnel: { |
| 49 | + style: { |
| 50 | + fill: { field: cell.category, scale: 'color' }, |
| 51 | + cornerRadius: 4 |
| 52 | + } |
| 53 | + }, |
| 54 | + transform: { |
| 55 | + style: { |
| 56 | + fill: { field: cell.category, scale: 'color' }, |
| 57 | + fillOpacity: 0.1 |
| 58 | + } |
| 59 | + }, |
| 60 | + outerLabel: { |
| 61 | + visible: true, |
| 62 | + line: { visible: false }, |
| 63 | + formatMethod: (data: any, datum: DataItem) => datum[array(cell.y)[0]], |
| 64 | + style: { |
| 65 | + fontSize: 24, |
| 66 | + fontWeight: 'bold', |
| 67 | + fill: 'black', |
| 68 | + limit: Infinity |
| 69 | + } |
| 70 | + }, |
| 71 | + extensionMark: [ |
| 72 | + index === 0 |
| 73 | + ? { |
| 74 | + type: 'text', |
| 75 | + dataIndex: 0, |
| 76 | + style: { |
| 77 | + text: (data: any) => data[array(cell.x)[0]], |
| 78 | + fontSize: 24, |
| 79 | + fill: 'grey', |
| 80 | + textAlign: 'center', |
| 81 | + x: (data: any, ctx: any) => { |
| 82 | + const { vchart } = ctx; |
| 83 | + return vchart.getCurrentSize().width / 2 - 10; |
| 84 | + }, |
| 85 | + y: (data: DataItem, ctx: any) => { |
| 86 | + const { getPoints } = ctx; |
| 87 | + const [tl, tr, br, bl] = getPoints(data); |
| 88 | + return (tl.y + bl.y) / 2; |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | + : null |
| 93 | + ].filter(Boolean) |
| 94 | + }; |
| 95 | + }; |
| 96 | + spec.series = [generateSeries(0, 'right'), generateSeries(1, 'left')]; |
| 97 | + return { spec }; |
| 98 | +}; |
| 99 | + |
| 100 | +const comparativeFunnelLegend = (context: GenerateChartInput) => { |
| 101 | + const { spec, cell } = context; |
| 102 | + spec.seriesField = cell.category; |
| 103 | + spec.legends = array(spec.legends).map(legend => ({ |
| 104 | + ...legend, |
| 105 | + id: 'legend', |
| 106 | + orient: 'top' |
| 107 | + })); |
| 108 | + return { spec }; |
| 109 | +}; |
| 110 | + |
| 111 | +const comparativeFunnelData = (context: GenerateChartInput) => { |
| 112 | + const { spec, dataTable } = context; |
| 113 | + const mp = {}; |
| 114 | + dataTable.forEach(item => { |
| 115 | + const { group } = item; |
| 116 | + if (!mp[group]) { |
| 117 | + mp[group] = []; |
| 118 | + } |
| 119 | + mp[group].push(item); |
| 120 | + }); |
| 121 | + spec.data = Object.entries(mp).map(([group, data]) => ({ id: group, values: data })); |
| 122 | + return { spec }; |
| 123 | +}; |
| 124 | + |
| 125 | +export const pipelineComparativeFunnel = [ |
| 126 | + title, |
| 127 | + formatXFields, |
| 128 | + layout, |
| 129 | + comparativeFunnelData, |
| 130 | + comparativeFunnelSeries, |
| 131 | + discreteLegend, |
| 132 | + comparativeFunnelLegend |
| 133 | +]; |
0 commit comments