echart的双y轴且可选图例的图表组件

376 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

echart的双y轴且可选图例的图表组件


一、效果图

在这里插入图片描述

二、构建组件

示例用的是vue和element ui演示的,对多选做了限制,只能同时选择2个

代码如下(示例):

<template>
  <div style="background:#ffffff">
    <div id="income" style="height:80vh;width:100%"></div>
    <div style="height: 70px; margin-left: 18%">
      <!-- 选择图例 -->
      <el-checkbox-group
        v-model="lengendList"
        @change="lengendChange"
        size="mini"
        :min="0"
        :max="2"
      >
        <el-checkbox
          v-for="city in lengendData"
          border
          :label="city"
          :key="city"
          >{{ city }}</el-checkbox
        >
      </el-checkbox-group>
    </div>
  </div>
</template>

<script>
//引入所需的echarts组件
import * as echarts from "echarts/core";
import { LineChart, BarChart } from "echarts/charts";
import { CanvasRenderer } from "echarts/renderers";
import {
  GridComponent,
  TooltipComponent,
  TitleComponent,
  LegendComponent,
  ToolboxComponent,
} from "echarts/components";

echarts.use([
  CanvasRenderer,
  LineChart,
  BarChart,
  TooltipComponent,
  GridComponent,
  TitleComponent,
  LegendComponent,
  ToolboxComponent,
]);

export default {
    name: 'myEchart',
  props: ['listData','title'],//父组件传入的数据和表名

  data() {
    return {
      // 图表的数据
      incomeChartData: {
        xAxis: [],
        reqSmt: [],
        resSmt:[],
        uniShowSmt:[],
        uniClkSmt:[],
        auctionPrice:[],
        winPrice:[],
        profit:[],
      },
      //图例的选项
      lengendData: [
        "请求数",
        "填充数",
        "展示数",
        "点击数",
        "支出",
        "收入",
        "利润",
      ],
      //默认选择的图例
      lengendList: ["展示数"],

      //图例的显示与否
      lengendList2: {
        请求数: false,
        填充数: false,
        展示数: true,
        点击数: false,
        支出: false,
        收入: false,
        利润: false,
      },
      timer: undefined,
    };
  },
  //监视listData数据,数据改变就重新初始化图表
  watch: {
    listData () {
      this.initIncomeChar();
    }
  },
  mounted() {
    //图表的大小随浏览器的大小变化而变化
    window.onresize = () => {
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.incomeChart.resize();
      }, 100);
    };
  },
  methods: {
  //得到dom元素,初始化图表
    initIncomeChar() {
      var chartDom = document.getElementById("income");
      this.incomeChart = echarts.init(chartDom);
      this.getIncomeData(this.listData);//对数据进行处理
    },
    //图表配置文件
    incomeSetOption() {
      const option = {
        title: {
          text: this.title,
          left: "center",
          textStyle: {
            color: "#333",
            lineHeight: 50,
          },
        },
        tooltip: {
          trigger: "axis",
        },
        legend: {
          data: this.lengendList,
          selected: this.lengendList2,
          top: "50",
          textStyle: {
            fontSize: 16,
          },
          itemHeight: 15,
          bottom: "20",
          height: "30",
        },
        grid: {
          top: "100",
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true,
        },
        toolbox: {
          itemSize: 20,
          right: "3%",
          top: "2%",
          feature: {
          //设置多个图表的功能组件
            dataZoom:[{
            type:"inside"
            }],
            magicType: {
              type: ['line', 'bar']
            },
            //对数据视图进行表格化,更好的观看性
            dataView:{
              readOnly:true,
              optionToContent: function(opt) {
                  var axisData = opt.xAxis[0].data;
                  var series = opt.series;
                  var table = '<table style="width:100%;text-align:center"><tbody><tr>'
                              + '<td>时间</td>'
                              + '<td>' + series[0].name + '</td>'
                              + '<td>' + series[1].name + '</td>'
                              + '<td>' + series[2].name + '</td>'
                              + '<td>' + series[3].name + '</td>'
                              + '<td>' + series[4].name + '</td>'
                              + '<td>' + series[5].name + '</td>'
                              + '<td>' + series[6].name + '</td>'
                              + '</tr>';
                  for (var i = 0, l = axisData.length; i < l; i++) {
                      table += '<tr>'
                              + '<td>' + axisData[i] + '</td>'
                              + '<td>' + series[0].data[i] + '</td>'
                              + '<td>' + series[1].data[i] + '</td>'
                              + '<td>' + series[2].data[i] + '</td>'
                              + '<td>' + series[3].data[i] + '</td>'
                              + '<td>' + series[4].data[i] + '</td>'
                              + '<td>' + series[5].data[i] + '</td>'
                              + '<td>' + series[6].data[i] + '</td>'
                              + '</tr>';
                  }
                  table += '</tbody></table>';
                  return table;
              }
            },
            saveAsImage: {}
          },
        },
        xAxis: {
          type: "category",
          boundaryGap: true,
          data: this.incomeChartData.xAxis,
        },
        //y轴设置两个,在下面的yAxisIndex配置项中,0和1分别代表设置的这两个y轴
        yAxis: [
          {
            type: "value",
            axisLine: {
              show: true,
            },
          },
          {
            type: "value",
            axisLine: {
              show: true,
            },
          },
        ],
        series: [
          {
            name: "请求数",
            type: "line",
            
            //通过查找选中的图例有没有自己来决定是显示在第几个y轴上
            //这样最后选择的两个图例中,肯定一个为0,一个为1 , 这样保证了两个不同的图例显示在不同的y轴
            yAxisIndex:
              this.lengendList.indexOf("请求数") == -1
                ? 0
                : this.lengendList.indexOf("请求数"),
            data: this.incomeChartData.reqSmt,
          },
          {
            name: "填充数",
            type: "line",
            yAxisIndex:
              this.lengendList.indexOf("填充数") == -1
                ? 0
                : this.lengendList.indexOf("填充数"),
            data: this.incomeChartData.resSmt,
          },
          {
            name: "展示数",
            type: "line",
            yAxisIndex:
              this.lengendList.indexOf("展示数") == -1
                ? 0
                : this.lengendList.indexOf("展示数"),
            data: this.incomeChartData.uniShowSmt,
          },
          {
            name: "点击数",
            type: "line",
            yAxisIndex: 1,
            yAxisIndex:
              this.lengendList.indexOf("点击数") == -1
                ? 0
                : this.lengendList.indexOf("点击数"),
            data: this.incomeChartData.uniClkSmt,
          },
          {
            name: "支出",
            type: "line",
            yAxisIndex: 1,
            yAxisIndex:
              this.lengendList.indexOf("支出") == -1
                ? 0
                : this.lengendList.indexOf("支出"),

            data: this.incomeChartData.auctionPrice,
          },
          {
            name: "收入",
            type: "line",
            yAxisIndex:
              this.lengendList.indexOf("收入") == -1
                ? 0
                : this.lengendList.indexOf("收入"),
            data: this.incomeChartData.winPrice,
          },
          {
            name: "利润",
            type: "line",
            yAxisIndex:
              this.lengendList.indexOf("利润") == -1
                ? 0
                : this.lengendList.indexOf("利润"),
            data: this.incomeChartData.profit,
          },
        ],
      };
      option && this.incomeChart.setOption(option);
    },

	//得到图表中的数据
    getIncomeData(data) {
      this.incomeChartData = {
        xAxis: [],
        reqSmt: [],
        resSmt: [],
        uniShowSmt: [],
        uniClkSmt: [],
        auctionPrice: [],
        winPrice: [],
        profit: [],
      };
      //一般父组件给的数据是按时间从大到小排,所以我们需要反转数据,这样在图表中才能从小到大排,这样在图表中才更加直观
      //反转数据后获取自己想要的数据
      data.reverse().forEach((item) => {
        this.incomeChartData.xAxis.push(item.reportTime);
        this.incomeChartData.reqSmt.push(item.reqSmt);
        this.incomeChartData.resSmt.push(item.resSmt);
        this.incomeChartData.uniShowSmt.push(item.uniShowSmt);
        this.incomeChartData.uniClkSmt.push(item.uniClkSmt);
        this.incomeChartData.auctionPrice.push(item.auctionPrice);
        this.incomeChartData.winPrice.push(item.winPrice);
        this.incomeChartData.profit.push(item.profit);
      });
      data.reverse();//反转数据后应该反转回来,不然会影响原数据
      this.incomeSetOption();//获取到数据后渲染图表
    },
    lengendChange() {
      // 将图例的显示先全部设为false,再将选中的图例设为true
      for (let i = 0; i < this.lengendData.length; i++) {
        this.lengendList2[this.lengendData[i]] = false;
      }
      for (let i = 0; i < 2; i++) {
        this.lengendList2[this.lengendList[i]] = true;
      }
      //选择图例后重新渲染图表
      this.incomeSetOption();
    },
  },
};
</script>