使用Echarts展示多层级数据案例

文章目录

  • 前言
  • 目标读者
  • 正文

前言

    ECharts 具有广大用户群,它是基于 JavaScript 开发的数据可视 化图表库。ECharts 支持几乎所有常用图表,对地理信息图形化和数 据化 3D 图形也支持良好。ECharts 本身具备丰富的示例,并且具有比 较完善的文档支撑,因此 ECharts 上手使用也相当简便快捷,完全满 足快速开发所见即所得的要求。
    尤其值得强调的是,ECharts 提供了非常灵活的个性化定制属性。对于不同的应用场景和设计需求,ECharts 处理起来都游刃有余,可谓是数据分析师的良师益友。
    本文将手把手把手教你“手撕”一个以 ECharts 为工具的整合多层级数据,创建一个相对复杂的数据大屏,并且根据需求进行个性定制的例子。

目标读者

    如果你想学习数据处理和分析,那么本文是为你准备的。本文将使用既容易理解,数据处理又相对简单的案例,带领你了解使用pandas进行数据处理的过程,以及如何选择数据展现模型进行数据可视化。
    如果你想了解和学习Web前台开发的相关技能,并且想熟练使用Echart,本文将带你学习Echart使用和配置方法,并进一步掌握更加复杂的数据可视化方法。对于如何配置Echarts中对象属性,本文也会耐心介绍如何查找和配置ECharts对象属性。
    如果你想学习python,并且想掌握Web后台技能,并搭建一个Web开发框架。那么本文也非常适合你。本文将搭建一个轻便极易上手的,以python为开发语言的Web框架。
    简而言之,本文适合想入门大数据处理和数据可视化,想使用python进行快速开发Web应用的读者。

正文

    本案例假设有这样一个需求:需要统计和显示各个城市以及下辖工厂的人员数量,对各个城市从业人员数量,以及工厂的人员数量进行排序。
    笔者已设计好数据库表模型,并且生成了案例所需数据。为了简化开发,并且方便初学者学习使用,本文使用sqlite数据库。下面的数据表city是存储在sqlite中的一个表,共计635条数据,其表结构如下:
     

    其中包括的数据样例如下:
     
    每个城市,以及其下辖工厂数量和城市工厂从业总人数统计如下:
           
    本案例使用python开发,数据操作使用pandas库。pandas可以帮助我们快速的进行数据清洗和处理,只需几条语句就可以将数据整理成我们想要的格式。
    因为需要统计每个城市工厂从业总人数并排序,还要排序城市下辖所有工厂人员数量。有两种思路解决这个问题。一是使用多个图表展示数据:一个图表按照城市分类将这一级别的工厂从业人员数据统计好,使用柱形图进行显示排序,接着再使用另一个图表展示城市下辖所有工厂的人员数量,按照多少排序显示;另外有一种方法是将所有数据都展示在同一个图表里。
    从数据处理过程的复杂度看,虽然第一种方法更符合数据分层处理和分析的过程,但是很明显的缺点是处理过程更加繁琐。相对来说,第二种方式在数据展示时更加方便快捷,但是对数据的处理和组织能力要求更高,需要深入了解pandas对数据对象的各种操作。
    本案例先使用第二种方法实现需求,随后会根据优化要求使用第一种方法再完善图表显示。
    Echarts提供了能够展示多层级数据的图表,比如旭日图和树图。从本质上看,这两种图表需要的数据结构是相同的,并且具有相似的对象元素,所以只要掌握其中一种展示方法即可。因为旭日图在展示时更易于比较数据的百比大小。本案例使用旭日图进行展示。
    Echarts提供了各种类型旭日图的示例。我们从这些优秀的例子中,选择下面这个基础例子为原型,最终一步一步修改成本案例需要的展示图形。
    Echarts旭日图基础案例
    从上面案例展示的源码分析,其中描述图形的json数据结构分为4个层级,每一层级是一辈人,图上显示的就是四世同堂的图像。而我们当前只需要两个层级,第一个层级是父级,对应到本例的数据是每个城市从业人员数量;第二个层级是子级,对应到本例就是每个城市下所有工厂的人员数量。
    按照我们的分析结果和数据要求,构造的json数据结构如下:

                 [{
                    "value": 18403,
                    "name": "城市01",
                    "path": "城市01",
                    "children": [{
                        "path": "城市01",
                        "name": "工厂01",
                        "value": 59
                    }, {
                        "path": "城市01",
                        "name": "工厂02",
                        "value": 57
                    }]
                }]

    这个json数据是一个数组,数组中有多个对象,每个对象对应本例中的一个城市,每个对象具有name,value,path,children四个属性,其中children是一个数组,数组中的每一个对象是一个工厂的人员数量,每个对象有path,name,value三个属性。其中path属性在父对象和子对象都存在,这就是两者联系的纽带了。
    我们按照分析写出自己的静态页面,主要部分代码如下:

<script type="text/javascript">
          var chartDom = document.getElementById('main');
          var myChart = echarts.init(chartDom);
          var option;
          var srData= [{
                    "value": 18403,
                    "name": "城市01",
                    "path": "城市01",
                    "children": [{
                        "path": "城市01",
                        "name": "工厂01",
                        "value": 59
                    }, {
                        "path": "城市01",
                        "name": "工厂02",
                        "value": 57
                    }, {
                        "path": "城市01",
                        "name": "工厂03",
                        "value": 883
                    }, {
                        "path": "城市01",
                        "name": "工厂04",
                        "value": 982
                    }, {
                        "path": "城市01",
                        "name": "工厂05",
                        "value": 93
                    }, {
                        "path": "城市01",
                        "name": "工厂06",
                        "value": 572
                    }, {
                        "path": "城市01",
                        "name": "工厂07",
                        "value": 492
                    }, {
                        "path": "城市01",
                        "name": "工厂08",
                        "value": 752
                    }, {
                        "path": "城市01",
                        "name": "工厂09",
                        "value": 813
                    }, {
                        "path": "城市01",
                        "name": "工厂10",
                        "value": 5
                    }, {
                        "path": "城市01",
                        "name": "工厂11",
                        "value": 739
                    }, {
                        "path": "城市01",
                        "name": "工厂12",
                        "value": 233
                    }, {
                        "path": "城市01",
                        "name": "工厂13",
                        "value": 785
                    }, {
                        "path": "城市01",
                        "name": "工厂14",
                        "value": 400
                    }, {
                        "path": "城市01",
                        "name": "工厂15",
                        "value": 599
                    }, {
                        "path": "城市01",
                        "name": "工厂16",
                        "value": 120
                    }, {
                        "path": "城市01",
                        "name": "工厂17",
                        "value": 906
                    }, {
                        "path": "城市01",
                        "name": "工厂18",
                        "value": 376
                    }, {
                        "path": "城市01",
                        "name": "工厂19",
                        "value": 117
                    }, {
                        "path": "城市01",
                        "name": "工厂20",
                        "value": 506
                    }, {
                        "path": "城市01",
                        "name": "工厂21",
                        "value": 822
                    }, {
                        "path": "城市01",
                        "name": "工厂22",
                        "value": 326
                    }, {
                        "path": "城市01",
                        "name": "工厂23",
                        "value": 985
                    }, {
                        "path": "城市01",
                        "name": "工厂24",
                        "value": 620
                    }, {
                        "path": "城市01",
                        "name": "工厂25",
                        "value": 990
                    }, {
                        "path": "城市01",
                        "name": "工厂26",
                        "value": 63
                    }, {
                        "path": "城市01",
                        "name": "工厂27",
                        "value": 449
                    }, {
                        "path": "城市01",
                        "name": "工厂28",
                        "value": 139
                    }, {
                        "path": "城市01",
                        "name": "工厂29",
                        "value": 212
                    }, {
                        "path": "城市01",
                        "name": "工厂30",
                        "value": 234
                    }, {
                        "path": "城市01",
                        "name": "工厂31",
                        "value": 273
                    }, {
                        "path": "城市01",
                        "name": "工厂32",
                        "value": 646
                    }, {
                        "path": "城市01",
                        "name": "工厂33",
                        "value": 0
                    }, {
                        "path": "城市01",
                        "name": "工厂34",
                        "value": 885
                    }, {
                        "path": "城市01",
                        "name": "工厂35",
                        "value": 571
                    }, {
                        "path": "城市01",
                        "name": "工厂36",
                        "value": 150
                    }, {
                        "path": "城市01",
                        "name": "工厂37",
                        "value": 413
                    }, {
                        "path": "城市01",
                        "name": "工厂38",
                        "value": 694
                    }, {
                        "path": "城市01",
                        "name": "工厂39",
                        "value": 442
                    }]
                }];
          const formatUtil = echarts.format;
          function getLevelOption() {
            return [
                {
                    itemStyle: {
                        borderWidth: 0,
                        gapWidth: 5
                    }
                },
                {
                    itemStyle: {
                        gapWidth: 1
                    }
                },
                {
                    colorSaturation: [0.35, 0.5],
                    itemStyle: {
                        gapWidth: 1,
                        borderColorSaturation: 0.6
                    }
                }
            ];
          }
          myChart.setOption(
          (option = {
              title: {
                  text: 'People of the factory in the city',
                  left: 'center'
              },
              animation: false,
              tooltip: {
                  formatter: function (info) {
                      var value = info.value;
                      var treePathInfo = info.treePathInfo;
                      var treePath = [];
                      for (var i = 1; i < treePathInfo.length; i++) {
                        treePath.push(treePathInfo[i].name);
                      }
                      return [
                          '<div class="tooltip-title">' +
                          formatUtil.encodeHTML(treePath.join('/')) +
                          '</div>',
                          'Head Count: ' + formatUtil.addCommas(value)
                      ].join('');
                  }
              },
              series: [
                  {
                      name: 'People of the factory in the city',
                      type: 'sunburst',
                      radius: ['40%', '80%'],
                      nodeClick: 'link',
                      visibleMin: 300,
                      label: {
                          show: true,
                          formatter: '{b}'
                      },
                      itemStyle: {
                        borderColor: '#fff'
                      },
                      levels: getLevelOption(),
                      data: srData
                  }
              ]
          })
          );
          option && myChart.setOption(option);
        </script>


    使用Echarts前需要引入Echarts库。使用下面语句时,需要指定cdn路径或者具体路径。    

<script src="cdn_path/echarts.min.js"></script>

    让图形显示在界面上,先创建画布。

    var chartDom = document.getElementById('main');
    var myChart = echarts.init(chartDom);

    Echarts中承载图形属性的对象是option,其中最重要的对象是series,这个对象中可以包含一个或者多个图形对象,我们的sunburst图形就在这个对象中。
    对于具体的对象属性含义可以参考Echarts配置手册。
    从上面静态页面的json结构可以看出,我们只列出了城市01的数据。在本地打开静态页面,其效果如图:     
    图像正确的显示了层级关系。值得特别注意的,在静态页面中,我们并没有按照人数排序对象数组,而旭日图已经按照数据的多少,从右上开始顺时针显示。接下来,按照json数据结构的分析,我们尝试组织好了全部的数据补充到静态页面。图像效果如图:     
    页面最终显示出来的结果还是挺绚丽壮观的。各个城市已经按照人员数量所占的百分比大小显示了,图像上每个大扇区表示对应城市从业人员数量,每个小扇区代表所属城市下每个工厂人员数量。
    当前数据可视化的结果基本满足当前项目的需求。
    令人不快的是,页面上显示的工厂名称黑压压一片连在一起,工厂名称无法看清,并且整体也不美观,这个问题是否能解决呢?
    好在Echarts是很成熟的图形库,其文档也相当完善。我们尝试通过查找文档来解决这个问题。
    首先找到文档位置配置手册的位置:https://echarts.apache.org/zh/option.html#title
    因为我们使用的是旭日图,找到旭日图的配置位置,如图:
     我们希望旭日图中每个小扇形足够宽的时候再显示工厂名称,这样工厂名称才能看得清楚一些。我们看看label下面有没有能够修改这一配置的属性。经过一番查找,我们发现旭日图的label对象中包括如下这个属性。     
    配置label对象的minAngle的含义是,该属性设置每个分类在旭日图的扇形中是否显示名称,当扇形的角度小于设置的角度就不再显示名称。在静态页面上修改后再试试看,果然有效果,页面一下变的清爽多了。对于感兴趣的城市,我们将鼠标指针指上去,就会弹出该扇区的名称和人员数量的信息。

     
    前台静态页面搞定了,界面数据可视化部分已经没有问题了。
    接下来我们把注意力转移到后台。
    后台数据的处理和将数据传递给前台才是重头戏,由于文章篇幅的关系,我们将在下一篇文章中描述。
 

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值