资讯详情

Echarts的二次封装思考心得。封装成果:折线柱状混合图、立体柱状折线混合图、markline标记线

先说说这个对ECharts让我们总结一封装的东西,感觉这是重点!

二次封装及使用的矛盾痛点:

  1. 一般包装只会暴露一些常见的属性,如图表的颜色和数据;
  2. 封装人员不会考虑包装所有情况,因为它毫无意义,比如图表上的文本大小。如果面具被考虑,最好不要包装,直接使用Echarts获得属性;
  3. 但在使用过程中,除了对颜色数据的不同要求外,确实会根据实际情况和设计草案进行调整,如图表的具体位置、图例的位置、文本的风格等

解决思路及方法:

以图表的位置为例Echarts中的属性为gird

1.在包装过程中,我们是对的grid设置默认值,如:
let gridDefault: EChartOption.Grid = { 
          left: 88,  right: 196,  bottom: 50,  top: 110, }; 
同时暴露一个grid属性,属性继承Echarts的grid属性
const Component = ({ 
         gird}:{ 
         grid?: EChartOption.Grid;})=>{ 
          return () } 
3、合并属性

使用时,若有,则用传递的值替换。 但

简单的属性还可以,可以直接覆盖替换,比如gird的left、right等等

但Echarts属性往往是,使用时间传参如果没有写,如果没有写,使用Object.assign()会导致深度默认属性

由于组件的二次开发,用户肯定不希望每个属性都传播,

针对这种情况,我发现了,他不像assign一样,,merge他会,相同的属性会被覆盖,

这样,在包装组件时,抛出的继承就是这样的Echarts组件的属性和默认属性一次merge。合并后即可。grid = merge(gridDefault, grid);

结论:

为了实现更高的组件自由度,抛出更多的继承Echarts代码中的属性merge默认值可以。这样,开发人员就不需要考虑组件需要什么属性,只需要考虑他们需要什么属性


说了这么多废话,开始贴代码。

先说说这次二次封装暴露出的功能

  • 柱状图的负值可以自定义颜色
  • 多柱多折线设置
  • 三个好看的立体柱
  • 折线的symbol
  • MarkLine标记线是柱还是折线
  • MarkPoint标记点展示最大最小值

示例图

在这里插入图片描述

上代码

第一个(所有参数了,见封装类型属性说明)

import React from "react"; import { 
         MultiBarAndLineCharts } from "组件路径的封装";  const Index: React.FC<{ 
        }> = () => { 
        
  let xAxisData = ["name1", "name2", "name3", "name4", "name5"];
  let barDataS = [
    [100, 200, 320.48, 200, -100],
    [50, -50, 50, -50, 100],
  ];
  let lineDataS = [[58, 81, 42, 98, 35]];
  let nameS = ["柱状图1", "柱状图2", "折线图1"];
  let yAxisNames = ["单位/亿元", ""];
  let color = ["rgb(254,163,61)", "rgb(17,145,222)", "rgb(54,68,192)"];
  let barNegativeNumberColor = ["rgb(254,163,61)", "rgb(196,76,78)"];
  return (
    <div
      style={ 
        { 
         width: "100%", height: "600px", background: "rgba(13,19,41)" }}
    >
      <MultiBarAndLineCharts
        xAxisData={ 
        xAxisData}
        barDataS={ 
        barDataS}
        lineDataS={ 
        lineDataS}
        nameS={ 
        nameS}
        color={ 
        color}
        barWidth={ 
        40}
        barNegativeNumberColor={ 
        barNegativeNumberColor}
        yAxisNames={ 
        yAxisNames}
      />
    </div>
  );
};
export default Index;

import React from "react";
import ReactEcharts from "echarts-for-react";
import { 
         EChartOption } from "echarts";
import { 
         merge } from "lodash";

const MultiBarAndLineCharts = ({ 
        
  grid,
  legend,
  tooltip,
  xAxis,
  yAxisNames = ["", ""],
  yAxis,
  xAxisData,
  barDataS,
  lineDataS,
  nameS,
  lineSymbol,
  barWidth = "auto",
  barNegativeNumberColor,
  borderWidth = 5,
  color,
  showLabel = [true, true],
  barLabel,
  lineLabel,
  customMarkLine = { 
        
    show: true,
    type: "line",
    title: "标记线",
    width: 2,
    color: "yellow",
    value: 50,
  },
  markLine,
  smooth = false,
}: { 
        
  /** * @description 直角坐标系内绘图网格,继承EChart.Grid */
  grid?: EChartOption.Grid;
  /** * @description 图例组件,继承EChart.Legend */
  legend?: EChartOption.Legend;
  /** * @description 提示框组件,继承EChart.Tooltip */
  tooltip?: EChartOption.Tooltip;
  /** * @description 直角坐标系 grid 中的 x 轴,继承EChart.XAxis */
  xAxis?: EChartOption.XAxis;
  /** * @description 两个y轴的名字 */
  yAxisNames?: string[];
  /** * @description 直角坐标系 grid 中的 y 轴,继承EChart.YAxis。 */
  yAxis?: EChartOption.YAxis[];
  /** * @description x轴数据 */
  xAxisData: string[];
  /** * @description 柱状图数据,二维数组,每个item是一组柱状图数据 */
  barDataS: number[][];
  /** * @description 折线图数据,二维数组,每个item是一组折线图数据 */
  lineDataS: number[][];
  /** * @description 柱状图和折线图的名字,这个参数是为了和legend对应起来 */
  nameS: string[];
  /** * @description 折线图的Symbol,需要是图片时使用,url为图片地址、size为大小 */
  lineSymbol?: { 
         url: string; size: number }[];
  /** * @description 柱状图每个柱子宽度 */
  barWidth?: number | string;
  /** * @description 当柱状图有负数,且需要单独设置颜色时使用。注意:若要使用,则每个柱子都要设置,即该属性长度等于barDataS属性长度 */
  barNegativeNumberColor?: string[];
  /** * @description 折线图item点的边框宽度 */
  borderWidth?: number;
  /** * @description 该图表的系列颜色 */
  color: string[];
  /** * @description 是否显示Label,是个数组,第一个参数控制柱状图label,第二个控制折线图label */
  showLabel?: boolean[];
  /** * @description 柱状图label,继承EChart.SeriesBar的Label,若有额外需求,参考EChart文档进行设置。因为没有对应的EChart的Label类型,所以给个any,自定义的时候要参考文档哦 */
  barLabel?: any;
  /** * @description 折线图label,继承EChart.SeriesLine的Label,若有额外需求,参考EChart文档进行设置。因为没有对应的EChart的Label类型,所以给个any,自定义的时候要参考文档哦 */
  lineLabel?: any;
  /** * @description 自定义MarkLine样式,包括:是否显示、属于bar还是line、文本、宽度、颜色、值 */
  customMarkLine?: { 
        
    show: boolean;
    type: "bar" | "line";
    title: string;
    width: number;
    color: string;
    value: number;
  };
  /** * @description MarkLine,因为没有对应的EChart的MarkLine类型,所以给个any,自定义的时候要参考文档哦 */
  markLine?: any;
  /** * @description 折线图是否是平滑曲线 */
  smooth?: boolean;
}) => { 
        
  let allSeries: EChartOption.Series[] = [];
  // 各种参数判断,有问题缺失抛出错误信息
  (function logErr() { 
        
    // 判断参数必填项
    if (!(xAxisData && barDataS && lineDataS && nameS && color))
      throw new SyntaxError("缺少必填的参数");
    // 判断每个系列的bar是不是都传进来一个负值的颜色,如果不是,抛出个错误
    if (
      barNegativeNumberColor &&
      barNegativeNumberColor.length !== barDataS.length
    )
      throw new SyntaxError(
        "barNegativeNumberColor属性的长度必须和barDataS的长度一致"
      );
    // 如果color长度不等于bar和line的长度和,抛出个警告
    if (color.length !== barDataS.length + lineDataS.length)
      console.warn("属性color的长度建议等于bar+line的长度");
    // name和数据的长度得一样,要不然没legend
    if (nameS.length !== barDataS.length + lineDataS.length)
      console.warn("属性nameS长度需要等于bar+line的长度");
  })();

  // merge默认参数和传递的参数
  (function mergeParams() { 
        
    let gridDefault: EChartOption.Grid = { 
        
      left: 88,
      right: 200,
      bottom: 50,
      top: 120,
    };
    let legendDefault: EChartOption.Legend = { 
        
      show: true,
      textStyle: { 
        
        color: "rgba(255, 255, 255, 1)",
        fontSize: 20,
        fontFamily: "pingFangMedium",
      },
      right: 0,
    };
    let tooltipDefault: EChartOption.Tooltip = { 
        
      show: true,
      trigger: "axis",
    };
    let xAxisDefault: EChartOption.XAxis = { 
        
      show: true,
      type: "category",
      axisLabel: { 
        
        fontSize: 30,
        color: "rgba(255, 255, 255, 0.65)",
        fontFamily: "pingFangMedium",
        padding: 0,
        interval: 0,
      },
      axisLine: { 
        
        show: true,
        lineStyle: { 
        
          type: "dashed",
          color: "rgba(208, 225, 245, 0.3)",
        },
      },
      axisTick: { 
        
        show: false,
      },
    };
    let yAxisDefault: EChartOption.YAxis[] = [
      { 
        
        show: true,
        type: "value",
        splitNumber: 5,
        name: yAxisNames[0],
        nameTextStyle: { 
        
          color: "rgba(133, 133, 133, 1)",
          fontSize: 18,
          fontFamily: "pingFangMedium",
          padding: [0, 0, 15, 0],
        },
        axisLabel: { 
        
          show: true,
          fontSize: 18,
          color: "rgba(133, 133, 133, 1)",
          formatter: (value: any) => { 
        
            return Math.ceil(value).toLocaleString("en-us");
          },
        },
        axisLine: { 
        
          show: false,
        },
        splitLine: { 
        
          lineStyle: { 
        
            type: "dashed",
            color: "rgba(208, 225, 245, 0.3)",
          },
        },
        axisTick: { 
        
          show: false,
        },
        max: (value: any) => { 
        
          return value.max + value.max / 10;
        },
        min: (value: any) => { 
        
          if (value.min < 0) return value.min + value.min / 4;
          else return 0;
        },
      },
      { 
        
        type: "value",
        name: yAxisNames[1],
        show: true,
        splitLine: { 
         show: false },
        axisLine: { 
         show: false },
        axisTick: { 
         show: false },
        axisLabel: { 
        
          show: true,
          fontSize: 18,
          color: "rgba(133, 133, 133, 1)",
          formatter: (params: any) => { 
        
            return `${ 
          params}%`;
          },
        },
      },
    ];
    let barLabelDefault = { 
        
      show: showLabel[0],
      color: "rgba(255, 255, 255, 1)",
      fontSize: 20,
      position: "top",
    };
    let lineLabelDefault = { 
        
      show: showLabel[1],
      color: "rgba(255, 255, 255, 1)",
      fontSize: 25,
      formatter: function (params: any) { 
        
        return params.value + "%";
      },
    };
    let markLineDefault = { 
        
      symbol: ["none", "none"],
      silent: true,
      lineStyle: { 
        
        type: "dashed",
        width: customMarkLine.width,
        color: customMarkLine.color,
      },
      label: { 
        
        show: true,
        fontSize: 22,
        position: "right",
        padding: [0, 0, 0, 18],
        formatter: function (params: any) { 
        
          return `${ 
          customMarkLine.title} (${ 
          params.value}${ 
           customMarkLine.type === "line" ? "%" : "" })`;
        },
      },
      data: [
        { 
        
          yAxis: customMarkLine.value,
        },
      ],
    };
    grid = merge(gridDefault, grid);
    tooltip = merge(tooltipDefault, tooltip);
    legend = merge(legendDefault, legend);
    xAxis = merge(xAxisDefault, xAxis);
    yAxis = merge(yAxisDefault, yAxis);
    barLabel = merge(barLabelDefault, barLabel);
    lineLabel = merge(lineLabelDefault, lineLabel);
    markLine = merge(markLineDefault, markLine);
  })();

  // 柱状图基本配置
  let barSeriesBasicConfig: EChartOption.SeriesBar = { 
        
    type: "bar",
    barWidth: barWidth,
    label: barLabel,
  };
  // 折线图图基本配置
  let lineSeriesBasicConfig: EChartOption.SeriesLine = { 
        
    type: "line",
    yAxisIndex: 1,
    lineStyle: { 
        
      width: 5,
    },
    symbolSize: 15,
    label: lineLabel,
    smooth,
  };

  // 处理柱状图数据
  barDataS.forEach((item, index) => { 
        
    let data: { 
        
      value: number;
      itemStyle?: { 
         color: string };
      label?: { 
         position: string };
    }[] 
        标签: m18圆柱型激光对射型传感器7klb动态轴重秤传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台