ECharts实现数据下钻

先讲原理:

  1. 初始化图表
  2. 绑定点击事件
  3. 拼好要下钻的option数据
  4. 重新渲染ECharts

 完整代码

<template>
  <!-- 月度项目汇总报表 -->
  <div class="box">
    <h2>数据下转模板</h2>
    <!-- 全局 id 不可重复 -->
    <div id="chart"></div>
  </div>
</template>
<script>
import * as echarts from "echarts";
export default {
  name: "chart",
  data() {
    return {
      chartData: [], //源数据
      stack: [], // 数据栈  用于数据下转
    };
  },
  methods: {
    getData() {
      // ...请求数据省略

      // 数据格式
      let data = [
        {
          label: "金额",
          type: "line",
          color:"#ed7d31",
          chartData: [
            {
              name: "位置1",
              value: 80,
              children: [
                {
                  name: "v11.0",
                  value: 10,
                },
                { name: "v10.0", value: 5 },
                { name: "v9.0", value: 4 },
                { name: "v8.0", value: 3 },
                { name: "v7.0", value: 2 },
                { name: "v6.0", value: 1 },
              ],
            },
            {
              name: "位置2",
              value: 20,
            },
            {
              name: "位置3",
              value: 30,
            },
            {
              name: "位置4",
              value: 80,
            },
            {
              name: "位置5",
              value: 18,
            },
          ],
        },
        {
          label: "采购金额",
          type: "bar",
          color:"#5470c6",
          chartData: [
            {
              name: "位置1",
              value: 80,
              children: [
                {
                  name: "v11.0",
                  value: 10,
                  children: [
                    { name: "w1", value: 10 },
                    { name: "w2", value: 800 },
                    { name: "w3", value: 700 },
                    { name: "w4", value: 20 },
                    { name: "w5", value: 500 },
                    { name: "w6", value: 40 },
                  ],
                },
                {
                  name: "v10.0",
                  value: 8,
                },
                { name: "v9.0", value: 7 },
                { name: "v8.0", value: 6 },
                { name: "v7.0", value: 5 },
                { name: "v6.0", value: 4 },
              ],
            },
            {
              name: "位置2",
              value: 21,
            },
            {
              name: "位置3",
              value: 31,
            },
            {
              name: "位置4",
              value: 81,
            },
            {
              name: "位置5",
              value: 19,
            },
          ],
        },
      ];
      this.chartData = data;
      console.log(this.chartData, "源数据");
      this.init(); //初始化echarts
    },
    init() {
      //   一、 初始化图表
      // 拼series数据
      let seriesData = this.spellData(this.chartData, "chartData");
      console.log(seriesData, "拼好的series数据");

      let option = {
        // 分类
        legend: {
          top: -5,
          left: 35,
        },
        // 提示
        tooltip: {
          trigger: "axis",
        },
        // 距离
        grid: {
          top: 25,
          left: 30,
          right: 5,
          bottom: 25,
        },
        xAxis: {
          data: this.chartData[0].chartData.map((item) => item.name), //以第一个数据为标准,因为name是一致的
        },
        yAxis: {},
        // series 数据
        series: [...seriesData],
        // 默认不显示返回按钮
        graphic: [
          {
            type: "text",
            left: 0,
            top: 1,
            style: {
              text: "",
              fontSize: 16,
            },
          },
        ],
      };
      let myChart = echarts.init(document.getElementById("chart"));
      myChart.setOption(option);

      //  二、 数据下砖
      // 记录栈
      this.stack = [];
      this.stack.push(option);
      // 点击事件
      let that = this;
      myChart.off("click"); // 点击之前 先把上一次的解绑,避免两次点击
      myChart.on("click", function (event) {
        // 数据下钻
        that.dataDrillDown(event);
      });
      //   自适应屏幕
      window.onresize = function () {
        myChart.resize();
      };
    },

    // 数据下转
    dataDrillDown(event) {
      console.log(event, "event");
      /* 
        数据下转的查询数据规则有两种
          1. 查询亲孩子(自己符合规则的数据)
          2. 查找所有孩子(只要name一致 并且也有children就一起渲染)  * 默认
      */
      //  这里使用的是第二种,如果想使用第一种 在数据下转前 查询父数据内符合规则的即可,而不是遍历全部的数据
      // const parentData = that.chartData.filter((item) => {
      //   if (item.type == event.seriesType && item.label == event.seriesName) {
      //     return item;
      //   }
      // });

      //  1.查找子数据 (这里拿数据的name进行查询的)
      let childrenData = [];
      function findChildren(arr, event, parentItem) {
        arr.filter((item) => {
          if (
            item.name === event.name &&
            item.children &&
            item.children.length != 0
          ) {
            item.label = parentItem.label;
            item.type = parentItem.type;
            item.color = parentItem.color;
            childrenData.push(item); //查到的children
          } else if (item.children && item.children.length != 0) {
            findChildren(item.children, event, parentItem);
          }
        });
      }
      this.chartData.forEach((item) => {
        findChildren(item.chartData, event, item);
      });

      if (childrenData.length == 0) return false; //如果查不到证明没有 直接return
      console.log(childrenData, "查到的所有符合规则数据");
      // 2.拼子series数据
      let childrenSeriesData = this.spellData(childrenData, "children");
      console.log(childrenSeriesData, "拼好的子series数据");

      // 3.初始化下转数据
      let option = {
        // 分类
        legend: {
          top: -5,
          left: 35,
        },
        // 提示
        tooltip: {
          trigger: "axis",
        },
        // 距离
        grid: {
          top: 25,
          left: 30,
          right: 5,
          bottom: 25,
        },
        xAxis: { data: childrenData[0].children.map((item) => item.name) },
        yAxis: {},
        series: [...childrenSeriesData],
      };

      this.stack.push(option); //记录栈
      let that = this;
      // 下转后的返回按钮
      option.graphic = [
        {
          type: "text",
          left: 0,
          top: 1,
          style: {
            text: "返回",
            fontSize: 16,
          },
          onclick: function (event) {
            // 返回到上一个
            let option = that.stack[that.stack.length - 2];
            if (!option) return false; // 到头了就停止执行
            // "如果是最前面一级  就不显示返回按钮"
            if (that.stack.length == 2) {
              option.graphic = [
                {
                  style: {
                    text: "",
                  },
                },
              ];
            }
            myChart.setOption(option); //重新渲染
            //点击一次返回 往栈里面删除一个
            that.stack.pop();
          },
        },
      ];
      let myChart = echarts.init(document.getElementById("chart"));
      myChart.setOption(option, true);
    },
    // 拼数据
    spellData(arr, dataName) {
      let seriesData = [];
      arr.forEach((item, index) => {
        if (!item[dataName]) item[dataName] = []; //边缘处理
        let obj = {
          color: item.color,
          /* 核心数据 */
          name: item.label,
          type: item.type,
          data: item[dataName].map((item) => item.value),
          /* 其他数据 */
          label: {
            show: true,
            position: "inside",
            fontSize: 18,
          },
          // 过渡时间和动画
          animationDurationUpdate: 500,
          universalTransition: {
            enabled: true,
            divideShape: "split",
          },
        };
        seriesData.push(obj);
      });
      return seriesData;
    },
  },
  mounted() {
    this.getData();
  },
};
</script>
<style scoped lang='scss'>
.box {
  position: absolute;
  width: 100%;
  height: 100%;
}
#chart {
  width: 100%;
  height: 90%;
}
</style>

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值