echart的封装

411 阅读5分钟

安装包 npm i echarts

封装组件 EchartComponent

  • 新建 src/components/EchartComponent.vue
<template>
  <div ref="echartComponentRef" style="height: 100%"></div>
</template>

<script>
import * as echarts from "echarts";
import debounce from "lodash/debounce"; // 防抖函数
import LineBarEchartModel from "./model/lineBarEchartModel";
export default {
  name: "BasicEchart",
  components: {},
  props: {
    options: {
      type: LineBarEchartModel,
      required: true,
      default: () => ({}),
    },
  },
  computed: {},
  data() {
    return {
      // 创建的echart实例,便于组件销毁时销毁该实例
      echartsInstance: {},
      resizeCb: () => {},
    };
  },
  created() {},
  beforeDestroy() {
    window.removeEventListener("resize", this.resizeCb);
  },
  destroyed() {
    this.echartsInstance.dispose && this.echartsInstance.dispose();
  },
  watch: {
    /**
     * @desc 数据改变时重新生成echart
     */
    options: {
      handler(options) {
        console.log("watch---options---start");
        this.echartRender(options);
      },
      deep: true,
    },
  },
  mounted() {
    this.resizeCb = debounce(this.resizeCallBack, 500);
    window.addEventListener("resize", this.resizeCb);
  },
  methods: {
    resizeCallBack() {
      console.log("EchartComponent---resizeCallBack");
      this.echartRender(this.options);
    },
    echartRender(options = {}) {
      this.echartsInstance.dispose && this.echartsInstance.dispose();
      const chartEle = this.$refs.echartComponentRef;
      // 初始化并设置 容器 + 颜色主题 + 宽高
      this.echartsInstance = echarts.init(chartEle, "", Object.keys(options.containerStyle).length > 0 ? options.containerStyle : null);
      LineBarEchartModel.supplyOptions(options);
      console.log("echartRender---options", JSON.stringify(options));
      options && this.echartsInstance.setOption(options);
    },
  },
};
</script>

<style lang="scss" scoped></style>

  • 新建 src/components/model/lineBarEchartModel.js
export default class LineBarEchartModel {
  /**
   * @desc echart所需配置模型   可参考 https://echarts.apache.org/zh/option.html#legen
   * @param {type}                line:折线图(默认值)   bar:柱状图
   * @param {title}               控制图标上方标题  title: {text:"金融-趋势图"} 默认位置在左边, 若需要在右边,传入第2个参数即可
   * @param {legend}              多个指标时必须提供, 当图标展示多个指标时的配置  legend: {data: ['Video', 'Music']},
   * @param {series }             每个指标在维度下对应的数据 series: [{data: [120, 132, 101], {data: [120, 132, 101]}]   name 和 type 不用传入
   * @param {xAxis}               x轴维度 xAxis: {data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']}
   * @param {containerStyle}      默认父容器的宽高 containerStyle  echart宽高
   * @param {isSeriesStack}       是否需要堆叠,默认值false:不堆叠
   * @param {yAxis}               默认只有左轴, 设置左右双Y轴:[{name:'左侧Y轴名称',position: 'left'}, {name:'右侧Y轴名称',position: 'right'}]
   * @param {dataZoom}            默认展示50%, 设置可以缩放X轴
   * @param {grid}                echart容器的占位
   */
  constructor() {
    this.type = "line";
    this.title = {};
    this.legend = {};
    this.series = {};
    this.xAxis = {};
    this.containerStyle = {};
    this.isSeriesStack = false;
    // this.setColors(['red','blue'])
    // 默认只有左轴
    this.yAxis = [
      {
        type: "value",
        splitLine: { show: false },
      },
    ];
    this.grid = { left: "10px", bottom: "10px", top: "60px", containLabel: true };
    this.tooltip = { trigger: "axis", extraCssText: "z-index:999", confine: true };
  }

  /**
   * @desc 设置图标类型
   */
  setType(type = "line") {
    this.type = type;
    return this;
  }

  /**
   * @desc 设置tooltip
   */
  setTooltip(tooltip = {}) {
    this.tooltip = tooltip;
    return this;
  }

  /**
   * @desc 设置色块
   * @param {colors}
   */
  setColors(colors = []) {
    this.color = colors;
    return this;
  }

  /**
   * @desc 设置 是否需要堆叠
   * @param {isSeriesStack}  是否需要堆叠,默认值false:不堆叠
   */
  setIsSeriesStack(isSeriesStack = false) {
    this.isSeriesStack = isSeriesStack;
    return this;
  }

  /**
   * @desc 设置图标标题   (right属性不设置,标题默认居左)
   */
  setTitle(title = {}) {
    this.title = title;
    return this;
  }

  /**
   * 多个指标项时需要设置
   * @param {*} legend
   */
  setLegend(legend = {}) {
    this.legend = legend;
    return this;
  }

  setLegendData(legendData = []) {
    this.legend = { data: legendData };
    return this;
  }

  /**
   * @desc 设置坐标值
   */
  setSeries(series = []) {
    this.series = series;
    return this;
  }

  setSeriesData(seriesData = []) {
    this.series = seriesData.map((series) => ({ data: series }));
    return this;
  }

  /**
   * @desc 设置x轴
   */
  setXAxis(xAxis = {}) {
    this.xAxis = { ...xAxis, boundaryGap: false };
    return this;
  }

  /**
   * @desc 设置x轴data
   */
  setXAxisData(xAxisData = []) {
    this.xAxis = { data: xAxisData, boundaryGap: false };
    return this;
  }

  /**
   * @desc 设置y轴最大 最小值
   * @param {minValue}
   * @return {maxValue}
   */
  setYAxisMinOrMax(minValue = 0, maxValue) {
    this.yAxis.forEach((item) => {
      if (minValue || minValue === 0) {
        item.min = minValue;
      }
      if (maxValue || maxValue === 0) {
        item.max = maxValue;
      }
    });
    return this;
  }

  setDoubleYAxisMinOrMax({ y1min = 0, y1max, y2min = 0, y2max }) {
    this.yAxis[0].min = y1min;
    this.yAxis[0].max = y1max;
    this.yAxis[1].min = y2min;
    this.yAxis[1].max = y2max;
    return this;
  }

  /**
   * @desc 设置y轴
   */
  setYAxis(yAxis = []) {
    this.yAxis = yAxis;
    return this;
  }

  /**
   * @desc 设置可以缩放X轴
   */
  setDataZoom() {
    this.dataZoom = [
      { type: "inside", start: 0, end: 100 },
      { start: 0, end: 100 },
    ];
    return this;
  }

  /**
   * @desc echart容器的占位
   */
  setGrid(grid = {}) {
    this.grid = grid;
    return this;
  }

  /**
   * @desc 设置echart容器样式, 如{width:300, height:100}
   */
  setContainerStyle(containerStyle = {}) {
    this.containerStyle = containerStyle;
    return this;
  }

  /**
   * @desc 完善 options 选项
   */
  static supplyOptions(options = {}) {
    const { type } = options;
    options?.series?.forEach((item, index) => {
      if (!item.type) {
        item.type = type;
      }
      item.smooth = true;
      if (options.isSeriesStack) {
        item.stack = "barSeriesStack";
      }
      // 左右双y轴时需要设定
      if (Array.isArray(options.yAxis) && options.yAxis.length > 1) {
        item.yAxisIndex = index;
      }
    });
    options?.legend?.data?.forEach((legendName, index) => {
      options.series[index].name = legendName;
    });
    // 数据展示是否从原点开始 type === 'bar'时 是从原点开始
    options.xAxis.boundaryGap = type === "bar";
    Object.assign(options);
  }
}

  • 使用组件
<template>
  <div id="app">
    <div class="echart_wrapper" style="height: 200px">
      <EchartComponent :options="lineBarEchartOpiton" />
    </div>
    <div class="echart_wrapper" style="height: 200px">
      <EchartComponent :options="lineBarEchartOpiton1" />
    </div>
  </div>
</template>

<script>
import LineBarEchartModel from "./components/model/lineBarEchartModel";
import EchartComponent from "./components/EchartComponent.vue";
export default {
  name: "App",
  components: {
    EchartComponent,
  },
  data() {
    return {
      lineBarEchartOpiton: new LineBarEchartModel(),
      lineBarEchartOpiton1: new LineBarEchartModel(),
      
    };
  },
  mounted() {
    this.lineBarEchartOpiton.setSeries([{ data: [100, 300, 200, 600, 50, 30] }]).setXAxis({ data: ["Mon", "Tue", "Wed", "T", "E", "F"] });
    this.lineBarEchartOpiton1
      .setLegendData(["O/N", "1W", "2W"])
      .setSeriesData([[100, 300, 200, 600, 50, 30],[300, 100, 30, 600, 50, 30],[10, 30, 20, 60, 150, 130]])
      .setXAxisData(["Mon", "Tue", "Wed", "T", "E", "F"]);
  },
};
</script>

  • 效果

image.png

使用介绍(如果只是简单设置数据,推荐setLegendData(datas)setSeriesData(datas)setXAxisData(datas)

  • 设置 折线图|柱状图 图表类型
// 折线图(默认折线图)
.setType("line")
// 柱状图
.setType("bar")
// 堆叠柱状图
.setType("bar").setIsSeriesStack(true)
  • 设置单一折线图
.setSeries([{ data: [100, 300, 200, 600, 50, 30] }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'] })
  • 设置多条折线图
.setLegend({ data: ["O/N", "1W", '2W', '3W','4W'] })
.setSeries([{ data: [100, 300, 200, 600, 50, 30] }, { data: [400, 150, 101, 200, 360, 300] }, { data: [300, 132, 101, 300, 100, 400] }, { data: [200, 132, 101, 150, 100, 400] }, { data: [800, 132, 101, 900, 100, 400] }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'], })
  • 设置单一柱状图
.setType("bar")
.setSeries([{ data: [100, 300, 200, 600, 50, 30] }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'] })
  • 设置多条柱状图
.setType("bar")
.setLegend({ data: ["O/N", "1W", '2W', '3W','4W'] })
.setSeries([{ data: [100, 300, 200, 600, 50, 30] }, { data: [400, 150, 101, 200, 360, 300] }, { data: [300, 132, 101, 300, 100, 400] }, { data: [200, 132, 101, 150, 100, 400] }, { data: [800, 132, 101, 900, 100, 400] }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'], })
  • 设置堆叠折线图
.setType("bar")
.setIsSeriesStack(true)
.setLegend({ data: ["O/N", "1W", '2W', '3W','4W'] })
.setSeries([{ data: [100, 300, 200, 600, 50, 30] }, { data: [400, 150, 101, 200, 360, 300] }, { data: [300, 132, 101, 300, 100, 400] }, { data: [200, 132, 101, 150, 100, 400] }, { data: [800, 132, 101, 900, 100, 400] }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'], })
  • 设置折现+柱状混合
.setType("bar")
.setLegend({ data: ["O/N", "1W", '2W'] })
.setSeries([{ data: [100, 300, 200, 600, 50, 30], type: "bar" }, { data: [600, 200, 100, 300, 60, 30], type: "bar" }, { data: [400, 150, 101, 200, 360, 300], type: "line" }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'] })
  • 设置左右双 Y 轴
.setLegend({ data: ["O/N", "1W"] })
.setSeries([{ data: [100, 300, 200, 600, 50, 30], type: "line" }, { data: [600, 200, 100, 300, 60, 30], type: "line" }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'] })
.setYAxis([{name:'左侧Y轴名称', position: 'left'}, {name:'右侧Y轴名称', position: 'right'}])
  • 设置水平参考线
.setLegend({ data: ["O/N", "1W"] })
.setSeries([{ data: [100, 300, 200, 600, 50, 30], type: "line", markLine: { data: [{name: 'Y 轴值为 100 的水平线',yAxis: 250}]} }, { data: [600, 200, 100, 300, 60, 30], type: "line" }])
.setXAxis({ data: ["Mon", "Tue", "Wed", 'T', 'E', 'F'] })