|
| 1 | +import { Sankey } from '@antv/gpt-vis'; |
| 2 | +import { Form, Input, Select } from 'antd'; |
| 3 | +import React, { useState } from 'react'; |
| 4 | + |
| 5 | +const data = [ |
| 6 | + { source: "Agricultural 'waste'", target: 'Bio-conversion', value: 124.729 }, |
| 7 | + { source: 'Bio-conversion', target: 'Liquid', value: 0.597 }, |
| 8 | + { source: 'Bio-conversion', target: 'Losses', value: 26.862 }, |
| 9 | + { source: 'Bio-conversion', target: 'Solid', value: 280.322 }, |
| 10 | + { source: 'Bio-conversion', target: 'Gas', value: 81.144 }, |
| 11 | + { source: 'Biofuel imports', target: 'Liquid', value: 35 }, |
| 12 | + { source: 'Biomass imports', target: 'Solid', value: 35 }, |
| 13 | + { source: 'Coal imports', target: 'Coal', value: 11.606 }, |
| 14 | + { source: 'Coal reserves', target: 'Coal', value: 63.965 }, |
| 15 | + { source: 'Coal', target: 'Solid', value: 75.571 }, |
| 16 | + { source: 'District heating', target: 'Industry', value: 10.639 }, |
| 17 | + { source: 'District heating', target: 'Heating and cooling - commercial', value: 22.505 }, |
| 18 | + { source: 'District heating', target: 'Heating and cooling - homes', value: 46.184 }, |
| 19 | + { source: 'Electricity grid', target: 'Over generation / exports', value: 104.453 }, |
| 20 | + { source: 'Electricity grid', target: 'Heating and cooling - homes', value: 113.726 }, |
| 21 | + { source: 'Electricity grid', target: 'H2 conversion', value: 27.14 }, |
| 22 | + { source: 'Electricity grid', target: 'Industry', value: 342.165 }, |
| 23 | + { source: 'Electricity grid', target: 'Road transport', value: 37.797 }, |
| 24 | + { source: 'Electricity grid', target: 'Agriculture', value: 4.412 }, |
| 25 | + { source: 'Electricity grid', target: 'Heating and cooling - commercial', value: 40.858 }, |
| 26 | +]; |
| 27 | + |
| 28 | +const themes = ['default', 'academy', 'dark'] as const; |
| 29 | +export const PALETTE = [ |
| 30 | + '#8459fc', |
| 31 | + '#ff89bd', |
| 32 | + '#1677ff', |
| 33 | + '#00c2ff', |
| 34 | + '#ff9a00', |
| 35 | + '#f2cc2e', |
| 36 | + '#7587dc', |
| 37 | + '#bd80fa', |
| 38 | +]; |
| 39 | + |
| 40 | +export const DEFAULT_COLOR_PALETTE = [ |
| 41 | + '#1783FF', |
| 42 | + '#F08F56', |
| 43 | + '#D580FF', |
| 44 | + '#00C9C9', |
| 45 | + '#7863FF', |
| 46 | + '#DB9D0D', |
| 47 | + '#60C42D', |
| 48 | + '#FF80CA', |
| 49 | + '#2491B3', |
| 50 | + '#17C76F', |
| 51 | +]; |
| 52 | + |
| 53 | +export const ACADEMY_COLOR_PALETTE = [ |
| 54 | + '#4e79a7', |
| 55 | + '#f28e2c', |
| 56 | + '#e15759', |
| 57 | + '#76b7b2', |
| 58 | + '#59a14f', |
| 59 | + '#edc949', |
| 60 | + '#af7aa1', |
| 61 | + '#ff9da7', |
| 62 | + '#9c755f', |
| 63 | + '#bab0ab', |
| 64 | +]; |
| 65 | + |
| 66 | +export default function SankeyDemo() { |
| 67 | + const [theme, setTheme] = useState<'default' | 'academy' | 'dark'>('default'); |
| 68 | + const [backgroundColor, setBackgroundColor] = useState<string>(''); |
| 69 | + const [palette, setPalette] = useState<string[]>([]); |
| 70 | + |
| 71 | + const onValuesChange = (changedValues: { |
| 72 | + theme: 'default' | 'academy' | 'dark'; |
| 73 | + lineWidth: number; |
| 74 | + backgroundColor: string; |
| 75 | + palette: string[]; |
| 76 | + }) => { |
| 77 | + if (changedValues.theme) setTheme(changedValues.theme); |
| 78 | + if (changedValues.backgroundColor !== undefined) |
| 79 | + setBackgroundColor(changedValues.backgroundColor); |
| 80 | + if (changedValues.palette !== undefined) { |
| 81 | + let newPalette = changedValues.palette; |
| 82 | + if (typeof newPalette === 'string') { |
| 83 | + try { |
| 84 | + newPalette = JSON.parse(newPalette); |
| 85 | + } catch { |
| 86 | + newPalette = []; |
| 87 | + } |
| 88 | + } |
| 89 | + setPalette(Array.isArray(newPalette) ? newPalette : []); |
| 90 | + } else { |
| 91 | + setPalette([]); |
| 92 | + } |
| 93 | + }; |
| 94 | + |
| 95 | + return ( |
| 96 | + <div> |
| 97 | + <Form |
| 98 | + layout="inline" |
| 99 | + style={{ marginBottom: 12 }} |
| 100 | + initialValues={{ theme, backgroundColor, palette }} |
| 101 | + onValuesChange={onValuesChange} |
| 102 | + > |
| 103 | + <Form.Item label="Theme" name="theme" style={{ marginBottom: 6 }}> |
| 104 | + <Select style={{ width: 120 }} options={themes.map((t) => ({ label: t, value: t }))} /> |
| 105 | + </Form.Item> |
| 106 | + <Form.Item |
| 107 | + label="Background" |
| 108 | + name="backgroundColor" |
| 109 | + rules={[ |
| 110 | + { |
| 111 | + pattern: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/, |
| 112 | + message: '请输入有效的色值编码,例如 #fff 或 #ffffff', |
| 113 | + }, |
| 114 | + ]} |
| 115 | + style={{ marginBottom: 6 }} |
| 116 | + > |
| 117 | + <Input placeholder="#ffffff" style={{ width: 120 }} /> |
| 118 | + </Form.Item> |
| 119 | + <Form.Item label="Palette" name="palette" style={{ marginBottom: 6 }}> |
| 120 | + <Select |
| 121 | + placeholder="选择调色板" |
| 122 | + style={{ width: 200 }} |
| 123 | + options={[ |
| 124 | + { |
| 125 | + label: `默认调色板: ${DEFAULT_COLOR_PALETTE.join(', ')}`, |
| 126 | + value: JSON.stringify(DEFAULT_COLOR_PALETTE), |
| 127 | + }, |
| 128 | + { |
| 129 | + label: `学术风格调色板: ${ACADEMY_COLOR_PALETTE.join(', ')}`, |
| 130 | + value: JSON.stringify(ACADEMY_COLOR_PALETTE), |
| 131 | + }, |
| 132 | + { label: `内置调色板: ${PALETTE.join(', ')}`, value: JSON.stringify(PALETTE) }, |
| 133 | + ]} |
| 134 | + allowClear |
| 135 | + /> |
| 136 | + </Form.Item> |
| 137 | + </Form> |
| 138 | + <Sankey |
| 139 | + data={data} |
| 140 | + title="Sankey Chart Example" |
| 141 | + theme={theme} |
| 142 | + style={{ backgroundColor, palette }} |
| 143 | + /> |
| 144 | + </div> |
| 145 | + ); |
| 146 | +} |
0 commit comments