ECharts动态生成yData

import { EMPTY_LIST } from '@/common/parameter';
import { Radio } from 'antd';
import * as echarts from 'echarts';
import React, { useEffect, useRef, useState } from 'react';
const ChartComponents: React.FC = ({ dataSource = EMPTY_LIST, loading }: { loading?: boolean; dataSource?: any[] }) => {
  const [type, setType] = useState('pow');
  const arrRef = useRef([]);
  const [optionData, setOptionData] = useState({
    tooltip: {
      trigger: 'axis',
    },
    legend: {
      orient: 'vertical', // 垂直排列
      right: 5, // 距离右侧的距离
      top: 10,
      data: [],
    },
    grid: {
      left: '1%',
      top: '2%',
      bottom: '8%',
      right: '15%',
      containLabel: true,
    },
    dataZoom: [
      {
        id: 'dataZoomX',
        type: 'slider',
        start: 0,
        end: 100,
        zoomLock: false,
        handleSize: '80%', // 设置滑块的大小
        top: 'bottom', // 设置滑块的位置
      },
    ],
    xAxis: {
      type: 'category',
      boundaryGap: false,
      splitLine: {
        show: false,
      },
      axisLine: {
        lineStyle: {
          color: '#5c5d89',
        },
      },
      axisTick: {
        show: false,
      },
      axisLabel: {
        textStyle: {
          color: '#5c5d89',
        },
      },
      data: [],
    },
    yAxis: [
      {
        type: 'value',
        axisLabel: {
          textStyle: {
            color: '#a8aab0',
            fontStyle: 'normal',
            fontFamily: '微软雅黑',
            fontSize: 12,
          },
        },
        axisLine: {
          show: false,
        },
        axisTick: {
          show: false,
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#E5E9ED',
            // 	opacity:0.1
          },
        },
      },
    ],
    series: [],
  });

  const handleChange = (e: any) => {
    setType(e.target.value);
  };

  // 动态修改max,min.echarts会根据max,min自动设置区间
  const updateIntervalToDefaultTenFold = (myChart: any) => {
    const axisLabels = myChart.getModel().getComponent('yAxis', 0).axis.scale.getExtent(); // 获取[min,max]
    if (axisLabels.length > 0) {
      const diff = (axisLabels[1] - axisLabels[0]) / 10;
      return {
        max: Math.ceil(axisLabels[1] + diff), // 向上取整
        min: Math.floor(axisLabels[0] - diff), // 向下取整
      };
    }
  };

  const initChart = (legendList: string[], xData: string[], seriesData = []) => {
    let myChart = echarts.getInstanceByDom(document.getElementById('echarts-line'));
    if (myChart == null) {
      // 如果不存在,就进行初始化。
      myChart = echarts.init(document.getElementById('echarts-line'));
    }
    let obj = {
      ...optionData,
      legend: {
        ...optionData.legend,
        data: legendList,
      },
      dataZoom: [
        {
          id: 'dataZoomX',
          type: 'slider',
          start: xData[0],
          end: xData[xData.length - 1],
          zoomLock: false,
          handleSize: '80%', // 设置滑块的大小
          top: 'bottom', // 设置滑块的位置
        },
      ],
      xAxis: {
        ...optionData.xAxis,
        data: xData,
      },
      series: seriesData,
    };

    /**
     * 当按钮类型是linear,为 yAxis 或者 yAxis某一项 新增 max,min属性
     * 当按钮类型是pow,要删除max,min属性,不然图不会动态变化
     * */
    if (type === 'linear') {
      const { max, min } = updateIntervalToDefaultTenFold(myChart);
      obj.yAxis[0]['max'] = max;
      obj.yAxis[0]['min'] = min;
    } else {
      delete obj.yAxis[0]['max']; // 恢复默认间隔
      delete obj.yAxis[0]['min']; // 恢复默认间隔
    }
    setOptionData(obj);
    // 绘制图表,第二属性在动态变化时非常有用
    myChart.setOption(obj, true);
  };

  // 自动生成颜色
  const generateRandomColor = () => {
    const letters = '0123456789ABCDEF';
    let color = '#';
    for (let i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 12)];
    }
    return color;
  };

  const seriesOption = (legendList: string[], chartData: any, item: string, index: number) => {
    let obj = {
      name: item,
      type: 'line',
      data: [],
    };
    // 在pow模式下,会自动生成颜色,linear模式下颜色不变,和pow模式保持一致
    if (type !== 'linear') {
      obj['itemStyle.normal.color'] = generateRandomColor();
    }
    obj.data = chartData[`${'yData' + index}`];
    arrRef.current.push(obj);
  };
  useEffect(() => {
    let legendList: string[] = []; // 图例名称,根据实际情况看是否需要过滤
    // 因为需要动态生成多个yData,为了方便传参,设置一个对象
    let chartData = {
      xData: [],
    };
    arrRef.current = [];
    // dataSource是接口返回的内容,根据真实情况做变动
    if (dataSource.length) {
      dataSource.map((item: any, index: number) => {
        legendList.push(item.title.description);
        if (index === 0) {
          item.values.map((t: any) => {
            chartData.xData.push(t.t);
          });
        }
        chartData[`${'yData' + index}`] = []; // 动态生成 yData0,yData1...
        item.values.map((v: any) => {
          chartData[`${'yData' + index}`].push(v.v);
        });
      });
      legendList.map((item: any, index: number) => {
        seriesOption(legendList, chartData, item, index);
      });
      initChart(legendList, chartData.xData, arrRef.current);
    }
  }, [dataSource, type]);

  useEffect(() => {
    handleChange({ target: { value: 'pow' } });
  }, [dataSource]);

  return (
    <div>
      <div style={{ marginBottom: 15, width: '100%', textAlign: 'end' }}>
        <Radio.Group value={type} buttonStyle="solid" size="small" onChange={handleChange}>
          <Radio.Button value="pow">pow</Radio.Button>
          <Radio.Button value="linear">linear</Radio.Button>
        </Radio.Group>
      </div>
      <div id={'echarts-line'} style={{ width: '100%', height: '520px' }}></div>
    </div>
  );
};

export default ChartComponents;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值