| | |
| | | }; |
| | | } |
| | | |
| | | /** 中国地图 + 仓库节点 */ |
| | | function generateStardust(nodes: Array<{ value: number[] }>, count = 50): Array<{ value: number[] }> { |
| | | const particles: Array<{ value: number[] }> = []; |
| | | // 中国地理范围:经度 73~135,纬度 18~54 |
| | | const lngRange = [75, 132]; |
| | | const latRange = [20, 52]; |
| | | for (let i = 0; i < count; i++) { |
| | | // 种子式分布:部分粒子靠近仓库节点,部分随机 |
| | | if (i < count * 0.4 && nodes.length > 0) { |
| | | const seed = nodes[i % nodes.length]; |
| | | const [lng, lat] = seed.value; |
| | | particles.push({ |
| | | value: [lng + (Math.random() - 0.5) * 6, lat + (Math.random() - 0.5) * 4], |
| | | }); |
| | | } else { |
| | | particles.push({ |
| | | value: [ |
| | | lngRange[0] + Math.random() * (lngRange[1] - lngRange[0]), |
| | | latRange[0] + Math.random() * (latRange[1] - latRange[0]), |
| | | ], |
| | | }); |
| | | } |
| | | } |
| | | return particles; |
| | | } |
| | | |
| | | /** 中国地图 + 仓库节点(高级光态特效版) */ |
| | | export function getChinaMapOptions( |
| | | warehouseNodes: Array<{ name: string; value: number[]; stock: number }>, |
| | | flyLines: Array<{ from: string; to: string }> = [], |
| | | ): EChartsOption { |
| | | const nodeData = warehouseNodes.map((n) => ({ |
| | | name: n.name, |
| | | value: [...n.value, n.stock], |
| | | })); |
| | | |
| | | const maxStock = Math.max(1, ...warehouseNodes.map((n) => Math.abs(n.stock))); |
| | | |
| | | // 节点光晕尺寸映射 |
| | | function glowSize(stock: number, base: number, range: number) { |
| | | return base + (Math.abs(stock) / maxStock) * range; |
| | | } |
| | | |
| | | const stardust = generateStardust(warehouseNodes, 50); |
| | | |
| | | return { |
| | | geo: { |
| | | map: 'china', |
| | | roam: false, |
| | | label: { show: false }, |
| | | // 底层区域发光:用两层 geo 实现,这里增强主 geo 样式 |
| | | itemStyle: { |
| | | areaColor: { |
| | | type: 'linear', |
| | | x: 0, y: 0, x2: 0, y2: 1, |
| | | colorStops: [ |
| | | { offset: 0, color: '#0d1f42' }, |
| | | { offset: 0.5, color: '#0a1835' }, |
| | | { offset: 1, color: '#081028' }, |
| | | { offset: 0, color: '#0d1f4a' }, |
| | | { offset: 0.4, color: '#0a1838' }, |
| | | { offset: 0.7, color: '#08102a' }, |
| | | { offset: 1, color: '#060e20' }, |
| | | ], |
| | | }, |
| | | borderColor: 'rgba(0, 229, 255, 0.22)', |
| | | borderWidth: 1.2, |
| | | shadowColor: 'rgba(0, 229, 255, 0.08)', |
| | | borderColor: 'rgba(0, 229, 255, 0.28)', |
| | | borderWidth: 1.5, |
| | | shadowBlur: 18, |
| | | shadowColor: 'rgba(0, 180, 255, 0.25)', |
| | | shadowOffsetX: 0, |
| | | shadowOffsetY: 3, |
| | | shadowOffsetY: 0, |
| | | }, |
| | | emphasis: { |
| | | itemStyle: { |
| | | areaColor: '#132848', |
| | | borderColor: 'rgba(0, 229, 255, 0.45)', |
| | | borderWidth: 1.5, |
| | | }, |
| | | disabled: true, |
| | | }, |
| | | // 第二层 outline 通过 zlevel 更高的 border 模拟 |
| | | regions: [], |
| | | }, |
| | | series: [ |
| | | // ====== Series 0: 外层光晕(大尺寸、极低透明度) ====== |
| | | { |
| | | name: 'outerGlow', |
| | | type: 'scatter', |
| | | coordinateSystem: 'geo', |
| | | data: nodeData, |
| | | symbolSize: (val: number[]) => glowSize(val[2] || 0, 50, 30), |
| | | silent: true, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'radial', |
| | | x: 0.5, y: 0.5, r: 0.5, |
| | | colorStops: [ |
| | | { offset: 0, color: 'rgba(0,229,255,0.12)' }, |
| | | { offset: 0.3, color: 'rgba(0,229,255,0.05)' }, |
| | | { offset: 1, color: 'rgba(0,229,255,0)' }, |
| | | ], |
| | | }, |
| | | }, |
| | | emphasis: { disabled: true }, |
| | | zlevel: 1, |
| | | }, |
| | | // ====== Series 1: 内层光晕(中等尺寸,脉动式) ====== |
| | | { |
| | | name: 'innerGlow', |
| | | type: 'scatter', |
| | | coordinateSystem: 'geo', |
| | | data: nodeData, |
| | | symbolSize: (val: number[]) => glowSize(val[2] || 0, 26, 18), |
| | | silent: true, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'radial', |
| | | x: 0.5, y: 0.5, r: 0.5, |
| | | colorStops: [ |
| | | { offset: 0, color: 'rgba(0,255,200,0.22)' }, |
| | | { offset: 0.4, color: 'rgba(0,229,255,0.1)' }, |
| | | { offset: 1, color: 'rgba(0,150,255,0)' }, |
| | | ], |
| | | }, |
| | | }, |
| | | emphasis: { disabled: true }, |
| | | zlevel: 2, |
| | | }, |
| | | // ====== Series 2: 主节点(effectScatter 涟漪光效) ====== |
| | | { |
| | | name: 'warehouseNodes', |
| | | type: 'effectScatter', |
| | | coordinateSystem: 'geo', |
| | | data: warehouseNodes.map((n) => ({ |
| | | name: n.name, |
| | | value: [...n.value, n.stock], |
| | | })), |
| | | symbolSize: (val: number[]) => Math.max(8, Math.min(22, (val[2] || 1) / 1500)), |
| | | data: nodeData, |
| | | symbolSize: (val: number[]) => Math.max(10, Math.min(26, glowSize(val[2] || 0, 10, 12))), |
| | | showEffectOn: 'render', |
| | | rippleEffect: { brushType: 'stroke', scale: 4, period: 4.5 }, |
| | | rippleEffect: { |
| | | brushType: 'stroke', |
| | | scale: 5.5, |
| | | period: 3.5, |
| | | color: { |
| | | type: 'radial', |
| | | x: 0.5, y: 0.5, r: 0.5, |
| | | colorStops: [ |
| | | { offset: 0, color: C.cyan }, |
| | | { offset: 0.4, color: 'rgba(0,229,255,0.5)' }, |
| | | { offset: 1, color: 'rgba(0,100,255,0)' }, |
| | | ], |
| | | }, |
| | | }, |
| | | label: { |
| | | show: true, |
| | | position: 'bottom', |
| | | distance: 8, |
| | | distance: 14, |
| | | formatter: '{b}', |
| | | fontSize: 10, |
| | | fontSize: 11, |
| | | fontWeight: 'bold', |
| | | color: C.textPrimary, |
| | | textShadowBlur: 8, |
| | | textShadowColor: 'rgba(0,229,255,0.5)', |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'radial', |
| | | x: 0.5, y: 0.5, r: 0.5, |
| | | colorStops: [ |
| | | { offset: 0, color: '#fff' }, |
| | | { offset: 0.3, color: C.cyan }, |
| | | { offset: 1, color: 'rgba(0,229,255,0.3)' }, |
| | | { offset: 0, color: '#ffffff' }, |
| | | { offset: 0.15, color: '#b5f0ff' }, |
| | | { offset: 0.45, color: C.cyan }, |
| | | { offset: 1, color: 'rgba(0,120,220,0.3)' }, |
| | | ], |
| | | }, |
| | | shadowBlur: 20, |
| | | shadowBlur: 28, |
| | | shadowColor: C.cyan, |
| | | }, |
| | | zlevel: 1, |
| | | emphasis: { |
| | | scale: 1.6, |
| | | itemStyle: { |
| | | shadowBlur: 40, |
| | | shadowColor: '#fff', |
| | | }, |
| | | label: { |
| | | fontSize: 13, |
| | | textShadowBlur: 14, |
| | | textShadowColor: 'rgba(0,229,255,0.8)', |
| | | }, |
| | | }, |
| | | zlevel: 3, |
| | | }, |
| | | // ====== Series 3: 亮核(白色高亮核心) ====== |
| | | { |
| | | name: 'nodeCores', |
| | | type: 'scatter', |
| | | coordinateSystem: 'geo', |
| | | data: nodeData, |
| | | symbolSize: (val: number[]) => Math.max(3, Math.min(7, glowSize(val[2] || 0, 3, 3))), |
| | | silent: true, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'radial', |
| | | x: 0.5, y: 0.5, r: 0.5, |
| | | colorStops: [ |
| | | { offset: 0, color: '#ffffff' }, |
| | | { offset: 0.5, color: 'rgba(255,255,255,0.7)' }, |
| | | { offset: 1, color: 'rgba(255,255,255,0)' }, |
| | | ], |
| | | }, |
| | | shadowBlur: 14, |
| | | shadowColor: '#fff', |
| | | }, |
| | | emphasis: { disabled: true }, |
| | | zlevel: 4, |
| | | }, |
| | | // ====== Series 4: 飞线(光流) ====== |
| | | { |
| | | name: 'flyLines', |
| | | type: 'lines', |
| | | coordinateSystem: 'geo', |
| | | data: flyLines.map((f) => { |
| | |
| | | x: 0, y: 0, x2: 1, y2: 1, |
| | | colorStops: [ |
| | | { offset: 0, color: C.cyan }, |
| | | { offset: 0.5, color: '#5ce6ff' }, |
| | | { offset: 1, color: C.green }, |
| | | ], |
| | | }, |
| | | curveness: 0.25, |
| | | width: 1.2, |
| | | opacity: 0.5, |
| | | curveness: 0.28, |
| | | width: 1.5, |
| | | opacity: 0.6, |
| | | shadowBlur: 8, |
| | | shadowColor: 'rgba(0,229,255,0.4)', |
| | | }, |
| | | effect: { |
| | | show: true, |
| | | period: 3, |
| | | trailLength: 0.4, |
| | | period: 2.5, |
| | | trailLength: 0.5, |
| | | symbol: 'arrow', |
| | | symbolSize: 6, |
| | | color: C.green, |
| | | symbolSize: 7, |
| | | color: { |
| | | type: 'radial', |
| | | x: 0.5, y: 0.5, r: 0.5, |
| | | colorStops: [ |
| | | { offset: 0, color: '#fff' }, |
| | | { offset: 0.5, color: C.green }, |
| | | { offset: 1, color: 'rgba(0,255,136,0)' }, |
| | | ], |
| | | }, |
| | | }, |
| | | zlevel: 1, |
| | | zlevel: 2, |
| | | }, |
| | | // ====== Series 5: 环境光尘(背景粒子) ====== |
| | | { |
| | | name: 'stardust', |
| | | type: 'scatter', |
| | | coordinateSystem: 'geo', |
| | | data: stardust, |
| | | symbolSize: 2, |
| | | silent: true, |
| | | itemStyle: { |
| | | color: 'rgba(100,200,255,0.5)', |
| | | shadowBlur: 4, |
| | | shadowColor: 'rgba(100,180,255,0.5)', |
| | | }, |
| | | emphasis: { disabled: true }, |
| | | zlevel: 0, |
| | | }, |
| | | ], |
| | | tooltip: { |