/* //y轴显示数据 Data:{ type:number, 0(实线) 1虚线(预测) 2(填充) name:string, yIndex:number, //yName的下标索引(第几个y坐标轴) data:string[], } props:{ closeTime:boolen //是否超过7天展示时间 yName:string || string[], //y轴名称 一个或多个 xData:string[], //x轴时间数据 dataList:Data[], //折线的数据列表 currentType:string, //当前选择那个tabs 需要外部更新当前选中type时传入 typeList:string[], //图表下的选择类型列表 onChange:(id:number)=>{} } */ import { Tabs } from 'antd'; import dayjs from 'dayjs'; import * as echarts from 'echarts'; import { useEffect, useRef, useState } from 'react'; import styles from './index.less'; const { TabPane } = Tabs; export const handleExportClick = () => { const canvas = document.getElementsByTagName('canvas'); if (canvas && canvas.length > 0) { return canvas[0].toDataURL('image/png'); } return null; }; // 图表模块 const ChartModule = (props) => { const chartDomRef = useRef(); const chartRef = useRef(); const { yName, closeTime = false, xData, dataList, typeList = [], onChange, currentType, chartType = 'line', legend = {}, } = props; const [curType, setCurType] = useState(currentType); useEffect(() => { chartRef.current = echarts.init(chartDomRef.current); window.addEventListener('resize', resetChart); return () => window.removeEventListener('resize', resetChart); }, []); useEffect(() => { if (!chartRef.current || !dataList || !chartType === 'gauge') { return; } const option = { ...defaultOption }; if (legend) { option.legend.textStyle = { ...option.legend.textStyle, ...legend.textStyle, }; if (legend.right) { option.legend.right = legend.right; } } let series = []; switch (chartType) { case 'gauge': series = option.series[dataList.type]; series.data = [dataList]; for (const key in option) { delete option[key]; } option.series = [series]; break; default: // 超过7天x轴显示年月日,不到7天显示时分 if (!closeTime && xData && xData.length > 1) { const timeFormat = Math.abs( dayjs(xData[xData?.length - 1]).diff(dayjs(xData[0]), 'days'), ) + 1; if (timeFormat > 150 || chartType === 'bar') { option.xAxis.data = xData.map((item) => dayjs(item).format('YYYY-MM'), ); } else if (timeFormat >= 7) { option.xAxis.data = xData.map((item) => dayjs(item).format('YYYY-MM-DD'), ); } else { option.xAxis.data = xData.map((item) => dayjs(item).format('YYYY-MM-DD HH:mm'), ); option.xAxis.axisLabel.formatter = (value) => value?.split(' ')[1]; } } else { option.xAxis.data = xData || []; } if (Array.isArray(yName)) { if (yName.length > 2) { option.grid.right = yName.length * 60; } option.yAxis = yName.map((item, index) => { return { ...option.yAxis[index], name: item }; }); option.series = dataList.map((item) => { return { ...option.series[item.type], name: item.name, data: item.data, yAxisIndex: item.yIndex || 0, }; }); } else { option.grid.right = 60; // 重置grid left 用于比对计算合适宽度 option.grid.left = 70; option.yAxis = { ...option.yAxis[0], name: yName }; option.series = dataList.map((item) => { item.data.forEach((dataItem) => { if (String(dataItem).length * 10 + 40 > option.grid.left) { option.grid.left = String(dataItem).length * 10 + 45; } }); return { ...option.series[item.type], name: item.name, data: item.data, // barWidth: dataList.length >= 4 ? 8 : 20, }; }); } // 柱状图需要开启boundaryGap避免和Y轴重合 if (chartType === 'bar') { option.xAxis.boundaryGap = true; delete option.legend.itemHeight; } else { option.xAxis.boundaryGap = false; option.legend.itemHeight = 0; } option.legend.data = dataList.map((item) => item.name); break; } // console.log(props, JSON.stringify(option)); chartRef.current.clear(); chartRef.current.setOption(option); chartRef.current.resize(); // if (typeList?.length > 0) setCurType(typeList[0]); }, [yName, xData, dataList, typeList, chartType]); useEffect(() => { setCurType(currentType); }, [currentType]); const resetChart = () => { if (chartRef.current) chartRef.current.resize(); }; return (
{typeList?.length > 0 && ( { setCurType(type); onChange(type); }} > {typeList.map((item) => ( ))} )}
); }; export default ChartModule; const colors = [ '#F5A623', '#4B9FEC', '#91cc75', '#5470c6', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', ]; const defaultOption = { color: colors, tooltip: { trigger: 'axis', textStyle: { fontSize: 24, // color: }, }, grid: { bottom: 30, left: 70, right: 50, }, xAxis: { type: 'category', boundaryGap: false, axisTick: { show: false }, nameTextStyle: { fontSize: '0.24rem', }, axisLabel: { fontSize: '0.24rem', }, data: [ '00:00', '01:15', '02:30', '03:45', '05:00', '06:15', '07:30', '08:45', ], }, yAxis: [ { type: 'value', name: '000', top: 20, nameTextStyle: { fontSize: '0.24rem', // align: 'left', padding: [0, 0, 15, 0], }, axisLabel: { fontSize: '0.2rem', }, axisLine: { show: false, // lineStyle: { // color: colors[0], // }, }, splitLine: { lineStyle: { type: 'dashed', }, }, }, { type: 'value', name: '111', top: 20, position: 'right', nameTextStyle: { fontSize: '0.24rem', align: 'center', padding: [0, 0, 15, 0], }, axisLabel: { fontSize: '0.2rem', }, axisLine: { show: true, lineStyle: { color: colors[7], }, }, splitLine: { lineStyle: { type: 'dashed', }, }, }, { type: 'value', name: '222', top: 20, position: 'right', offset: 80, nameTextStyle: { fontSize: '0.24rem', align: 'left', padding: [0, 0, 15, 0], }, axisLabel: { fontSize: '0.2rem', }, axisLine: { show: true, lineStyle: { color: colors[8], }, }, splitLine: { lineStyle: { type: 'dashed', }, }, }, ], series: [ { data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line', name: '进水水量', yAxisIndex: 0, smooth: 'true', // itemStyle:{ // color:'#be7bbe', // }, showSymbol: false, // 不展示拐点圆圈 }, { data: [130, 125, 828, 743, 1100], name: '预测出水量', yAxisIndex: 0, type: 'line', smooth: 'true', lineStyle: { normal: { width: 4, type: 'dashed', }, }, itemStyle: { color: '#be7bbe', }, showSymbol: false, // 不展示拐点圆圈 }, { data: [820, 772, 901, 934, 1290, 1120, 1320], name: '实际出水量', yAxisIndex: 0, type: 'line', smooth: 'true', showSymbol: false, // 不展示拐点圆圈 itemStyle: { color: '#50A3C8', }, areaStyle: { origin: 'number', color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [ { offset: 0, color: 'rgba(31,114,150,1)', }, { offset: 1, color: 'rgba(31,114,150,0.3)', }, ]), }, }, { data: [120, 200, 150, 80, 70, 110, 130], name: '实际出水量', type: 'bar', // barGap: 0.2, // barWidth: 30, }, { data: [ { value: 19, name: '负荷率', }, ], name: '负荷率', type: 'gauge', startAngle: 180, endAngle: 0, radius: '90%', min: 0, max: 100, splitNumber: 10, center: ['50%', '65%'], axisLine: { lineStyle: { width: 40, color: [ [0.33, '#a4f428'], [0.66, '#f6a842'], [1, '#e02b42'], ], }, }, axisPointer: { show: true, }, pointer: { icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z', length: '50%', width: 8, offsetCenter: [0, 0], itemStyle: { color: 'auto', }, }, axisTick: { show: false, }, splitLine: { show: false, }, axisLabel: { show: false, }, title: { offsetCenter: [0, '25%'], fontSize: '0.24rem', }, detail: { show: false, }, }, ], legend: { // 图例配置 // icon:'arrow', // width:'2', itemHeight: 0, // 远点宽度为0不显示原点 // right: '30%', data: ['进水水量', '预测出水量', '实际出水量'], lineStyle: {}, textStyle: { fontSize: '0.24rem', }, }, // toolbox: { // show: true, // feature: { // // dataZoom: { // // yAxisIndex: 'none' // // }, // // dataView: { readOnly: false }, // // magicType: { type: ['line', 'bar'] }, // restore: {}, // saveAsImage: {}, // }, // }, };