The choice of data visualization library in React, ListChart example (list switching echarts chart, similar data is the bar of the x-axis)

Table of contents

echarts

Native echarts+TS

ListChart.tsx

ListChartUtil.tsx

ReactECharts

React hooks encapsulate Echarts5 components (ts/js)

Compared

D3

Recharts

echarts

Echarts is developed by Baidu, which is more in line with the habits of Chinese people . It supports various types of charts and has good interactive performance. The documentation is detailed and friendly. It is highly recommended

shortcoming

  • Beginners may find Echarts difficult to configure and require additional learning costs .

  • The customizability of Echarts may cause the code to become verbose , increasing the workload and development time.

  • In some cases, Echarts may be slow when rendering large datasets, which requires other optimizations to improve performance.

Native echarts+TS

Native echats official documents and functions are more complete than echarts-for-react,

But echarts-for-react is more friendly to react support and easier to use

 

ListChart.tsx

import React, { useEffect, useRef, useState } from 'react';
import { List, Button} from 'antd';
import { LineChartOutlined, BarChartOutlined } from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components';
import * as echarts from "echarts";

import './ListChart.css'
import { LIST_NAME, CHART_OPTION,resize,findSubstrIdx } from '../utils/ListChartUtil';
import { ListChartStatus } from "./ListChartStatus";

const ListChart: React.FC<ListChartStatus> = ({ urlPre, proc_datas, board_name }) => {

    const chartRef = useRef<HTMLDivElement>(null); 
    const [selectedIdx, setselectedIdx] = useState<number>(0);
    const [isLine, setIsLine] = React.useState<boolean>(true);
    const proc_list = new Array(proc_datas.length).fill(null).map((val, i) => {
        return proc_datas[i].proc_name;
    });
    let chart: any = null;
    
    useEffect(() => {
        if (chartRef.current) {
            chart = echarts.init(chartRef.current);
            const {option,urlSufs}=getOption(proc_datas[selectedIdx])
            chart.setOption(option);
            resize(chart);
            chart.on('click', isLine ? 'xAxis' : 'series', function (params: any) {
                const clickDate= isLine ? params.value:params.seriesName;
                window.open(urlPre + '/' + urlSufs[findSubstrIdx(urlSufs, clickDate)] + '/index.html', '_blank');
            });
        }  
    }, [chartRef, selectedIdx, isLine]);

    const initDate_UrlSufs=(proc_data:any)=>{
        let urlSufs: string[] = [];
        let dates: string[] = [];
        proc_data.date_list.forEach((date: string, idx: number) => {
            urlSufs.push(date + '/' + proc_data.report_id_list[idx]);
            dates.push(date.substring(5));
        });
        return {dates,urlSufs};
    }
    const  getBarDates=(series:any)=>{
        const barDatas: any = [];
        LIST_NAME.forEach((_, idx) => {
            if (series[idx] && series[idx].length) {
                barDatas.push([LIST_NAME[idx], ...series[idx]])
            }
        })
        return barDatas;
    }
    const getOption=(proc_data:any)=>{
        const {dates,urlSufs}=initDate_UrlSufs(proc_data)
        const series = [proc_data.avg_list, proc_data.sigma3_up_list, proc_data.sigma3_up_target_list, proc_data.sigma3_down_list, proc_data.max_list, proc_data.min_list]
        let option = {  
            tooltip: CHART_OPTION.tooltip,
            legend: CHART_OPTION.legend,
            toolbox: CHART_OPTION.toolbox,
            yAxis: CHART_OPTION.yAxis,
            title: {
                text: proc_data ? board_name + ":" + proc_data.proc_name : board_name,
                subtext: "点击日期可跳转到详情报告",
            },
            xAxis: {
                type: 'category', // 类型为分类轴
                triggerEvent: true, // 是否触发鼠标事件
                data: isLine ? proc_data.date_list.map((date: string, idx: number) => {
                    return dates[idx]
                }) : null,
            },
            series: isLine ? LIST_NAME.map((_, idx) => {
                if (series[idx] && series[idx].length) {
                    return {
                        name: LIST_NAME[idx],
                        type: 'line',
                        data: series[idx],
                        emphasis: {
                            focus: 'series'
                        },
                    }
                }
            }) : dates.map((_, idx) => {
                return {
                    name: dates[idx],
                    type: 'bar',
                    event: 'click',
                    emphasis: {
                        focus: 'series'
                    },
                }
            }),

            dataset: isLine ? null : {
                source: [
                    ['pref', ...dates],
                    ...getBarDates(series)
                ]
            },
        };
        return {option,urlSufs};
    }
    return (<ProCard layout="center"  className="procard" ghost>
        <ProCard colSpan={6} ghost >
            <List
                size="small"
                bordered
                className='procard-list'
                dataSource={proc_list}
                renderItem={(item, index) => <List.Item key={Math.random()} className={selectedIdx === index ? 'selected' :undefined }
                    onClick={() => setselectedIdx(index)}>
                    {item}</List.Item>}
            />
        </ProCard>
        <ProCard colSpan={18} ghost >
            <div className="procard-button" >
                <Button className="ant-btn" icon={<LineChartOutlined />} onClick={() => setIsLine(true)} ></Button>
                <Button className="ant-btn" icon={<BarChartOutlined />} onClick={() => setIsLine(false)}></Button>
            </div>
            <div key={`divChart${Math.random()}`}
                ref={chartRef}
                className='chart'
                style={
   
   {
                    flex: 2,
                    flexDirection:"column",
                    height: "40vh",
                    paddingLeft: "1vw",
                }}
            ></div>
        </ProCard>
    </ProCard>
    )
}
export default ListChart;

ListChart.css

.procard {
    display: flex;
    padding-top: 10px;
}
.procard-list {
    overflow-y: scroll;
    height: 45vh;
}
.selected {
    background-color: #e6f7ff !important;
  }
.procard-button{
    display: flex;
    justify-content: flex-end;
    padding-right: 7vw;
}

ListChartUtil.tsx

​
export const LIST_NAME = ['avg', '3∑-up', '3∑-up-target', '3∑-down', 'max', 'min']

export const CHART_OPTION = {
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: "shadow"
    },
  },
  legend: {
    left: 'center',
    width: '35%',
    selected: {
      'min': false,
      '3∑-down': false,
    }
  },
  toolbox: {
    show: true,
    feature: {
      dataZoom: {
        yAxisIndex: 'none'
      },
      dataView: { readOnly: false },
      //   magicType: { type: ['line'] },
      restore: {},
      saveAsImage: {}
    },
    right: "10%"
  },
  yAxis: {
    type: 'value',
    axisLabel: {
      formatter: '{value}  '
    }
  },
}
const dom: any = [];  //所有echarts图表的数组
/**
 * 当屏幕尺寸变化时,循环数组里的每一项调用resize方法来实现自适应。
 * @param {*} eDom 
 */
export function resize(eDom: any) {
  dom.push(eDom);
  window.onresize = () => {
    dom.forEach((it: any) => {
      it.resize();
    })
  };
}

export function findSubstrIdx(arr: string[], substr: string): number {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].indexOf(substr) !== -1) {
      return i;
    }
  }
  return -1;
}

​

ReactECharts

React hooks encapsulate Echarts5 components (ts/js)
 

React+TypeScript encapsulates ECharts_react typescript echart_KzXuanCn's Blog-CSDN Blog

GitHub - hustcc/echarts-for-react: ⛳️ Apache ECharts components for React wrapper. A simple React wrapper for Apache echarts.

Compared

D3

is a data-driven document-based JavaScript library that is highly flexible and customizable , but requires more coding effort.

Recharts

It is a library based on React encapsulation, which uses the powerful drawing function of D3, making it easier to use React for data visualization .

advantage

  • Recharts is easy to use because it has a low number of customization options.

  • Integrates with React's lifecycle methods, making it easy to add to React applications, and supports Redux state managers.

  • Lightweight with less impact on memory and CPU.

  • Supports multiple styles, custom colors and animations.

shortcoming

  • Does not support all types of charts, no Echarts wide variety.

  • Less functions than Echarts

To sum up, if you need to design highly customized charts and have enough development experience, it may be more convenient to use Echarts. On the other hand, Recharts may be more suitable for quick and easy data visualization tasks and easy to integrate into React applications.

Guess you like

Origin blog.csdn.net/qq_28838891/article/details/131063427