echarts 进阶之同心扇形图多级联动

需求分析

前情提要

同心多扇形图,用于表示树形数据结构以及每一层级节点在该层总量中占比。

原始数据结构: 

{
  "name": "师资队伍",
  "value": 19,
  "children": [
    {
      "name": "基本情况",
      "value": 3,
      "children": [
        {
          "name": "师资规模",
          "value": 2
        },
        {
          "name": "进修情况",
          "value": 1
        }
      ]
    },
    {
      "name": "师资结构",
      "value": 6,
      "children": [
        {
          "name": "职称结构",
          "value": 2
        },
        {
          "name": "学历结构",
          "value": 1
        },
        {
          "name": "学缘结构",
          "value": 3
        }
      ]
    },
    {
      "name": "师资水平",
      "value": 10,
      "children": [
        {
          "name": "资深学术权威",
          "value": 2
        },
        {
          "name": "中年领军专家",
          "value": 2
        },
        {
          "name": "青年拔尖英才",
          "value": 4
        },
        {
          "name": "国际知名学者",
          "value": 2
        }
      ]
    }
  ]
}

以上仅显示了一个根节点,其他根节点的数据结构类似。

PS: 子节点值相加,和等于父节点的值。

需求定义

  1. 绘制同心多级扇形图,可视化显示节点数值以及在同深度占比情况。
  2. 当某一根节点legend点击隐藏或显示时,动态更新其关联的所有子节点。

echarts

简介

echarts是一款JS可视化图表生成工具,由百度提供.

GitHub: 

https://github.com/ecomfe/echarts

官网: 

http://echarts.baidu.com/index.html

相比于其他图表生成工具: 

等, echarts 的风格对国内开发者来说, 显然更加友好。

获取引入

NPM:

npm install echarts --save

下载地址:  http://echarts.baidu.com/download.html

CDN: 

https://cdnjs.cloudflare.com/ajax/libs/echarts/3.8.5/echarts.min.js

情景分析

通过查看echarts官方实例(CV大法),我们可以轻松实现 要求1 : 

 绘制同心多级扇形图,可视化显示节点数值以及在同深度占比情况。

http://echarts.baidu.com/demo.html#pie-nest

然而即使翻遍文档也没有可拿的代码来实现 要求2:

当点击legend 控制节点数据的隐藏或显示时,动态更新其关联的所有子节点。

PS:  CV大法虽好使,可不要过度依赖!

需求实现

演变数据结构

显然,原始数据结构在这里很畸形,我们需要解析并更改使之更适用于现在这种情形。

无论使用循环还是递归来演变(这里省略了这一过程,线性组合),我们需要的最终数据结构如下:

{
  "level1": [
    {
      "name": "师资队伍",
      "color": "#2196F3",
      "category": 0,
      "value": 19
    }
  ],
  "level2": [
    {
      "name": "基本情况",
      "color": "#2196F3",
      "category": 0,
      "value": 3
    },
    {
      "name": "师资结构",
      "color": "#E3F2FD",
      "category": 0,
      "value": 6
    },
    {
      "name": "师资水平",
      "color": "#BBDEFB",
      "category": 0,
      "value": 10
    }
  ],
  "level3": [
    {
      "name": "师资规模",
      "color": "#2196F3",
      "category": 0,
      "value": 2
    },
    {
      "name": "进修情况",
      "color": "#E3F2FD",
      "category": 0,
      "value": 1
    },
    {
      "name": "职称结构",
      "color": "#BBDEFB",
      "category": 0,
      "value": 2
    },
    {
      "name": "学历结构",
      "color": "#90CAF9",
      "category": 0,
      "value": 1
    },
    {
      "name": "学缘结构",
      "color": "#64B5F6",
      "category": 0,
      "value": 3
    },
    {
      "name": "资深学术权威",
      "color": "#42A5F5",
      "category": 0,
      "value": 2
    },
    {
      "name": "中年领军专家",
      "color": "#2196F3",
      "category": 0,
      "value": 2
    },
    {
      "name": "青年拔尖英才",
      "color": "#1E88E5",
      "category": 0,
      "value": 4
    },
    {
      "name": "国际知名学者",
      "color": "#1976D2",
      "category": 0,
      "value": 2
    }
  ]
}

数据联动

一切关联问题的解决, 都只在于一个唯一标识的确立,这里我们使用的是 category (根节点数组下标)。

万事俱备,只欠一个 触发事件(国内外知名插件对于事件的封装和处理都很到位,API也是极尽简单)。

翻阅文档: http://echarts.baidu.com/api.html#events

 legend点选事件:

myChart.on('legendselectchanged', function (params) {
    console.log(params);
});

具体实现可在 源码 中查看。

PS

别问我color怎么来的,我会告诉你吗?

如果翻墙了,可以参考这个网站(专业配色):

https://material.io/guidelines/style/color.html#color-color-palette 

部分颜色截图:

我把这些组成了一个JSON以备不时之需, 如下所示:

{
  "data": [
    {
      "category": "蓝色",
      "color": "#2196F3",
      "sub": ["#2196F3","#E3F2FD", "#BBDEFB", "#90CAF9", "#64B5F6", "#42A5F5","#2196F3", "#1E88E5", "#1976D2", "#1565C0", "#0D47A1","#82B1FF", "#448AFF", "#2979FF", "#2962FF"]
    },
    {
      "category": "红色",
      "color": "#F44336",
      "sub": ["#F44336","#FFEBEE", "#FFCDD2", "#EF9A9A", "#E57373", "#EF5350","#F44336", "#E53935", "#D32F2F", "#C62828", "#B71C1C","#FF8A80", "#FF5252", "#FF1744", "#D50000"]
    },
    {
      "category": "绿色",
      "color": "#4CAF50",
      "sub": ["#4CAF50","#E8F5E9", "#C8E6C9", "#A5D6A7", "#81C784", "#66BB6A","#4CAF50", "#43A047", "#388E3C", "#2E7D32", "#1B5E20"]
    },
    {
      "category": "橘色",
      "color": "#FF9800",
      "sub": ["#FFF3E0","#FFE0B2", "#FFCC80", "#FFB74D", "#FFA726", "#FF9800","#FB8C00", "#F57C00", "#EF6C00", "#E65100", "#FFD180","#FFAB40", "#FF9100", "#FF6D00"]
    },
    {
      "category": "紫色",
      "color": "#9C27B0",
      "sub": ["#F3E5F5","#E1BEE7", "#CE93D8", "#BA68C8", "#AB47BC", "#9C27B0","#8E24AA", "#7B1FA2", "#6A1B9A", "#4A148C", "#EA80FC","#E040FB", "#D500F9", "#AA00FF"]
    }
  ]
}

源码

我将这一段代码单独提取出来放在这里, 本地新建.html文件, 复制粘贴即可在浏览器查看:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>chart</title>
</head>
<body>

<div id="graph" style="height: 600px;"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/echarts/3.8.5/echarts.min.js"></script>
<script type="text/javascript">
	(function(config){
		let chart = echarts.init(document.getElementById("graph"));

	    /**
	     * @params params
	     * params.name 标识当前点击的legend
	     * params.selected 标识当前选中的legend集合
	     */
        chart.on('legendselectchanged', function (params) {
            let options = this.getOption(), keys = Object.keys(params.selected), selected = [];

            // 获取选中目录的 category 值
            for(let item of keys) {
                if(params.selected[item]) {
                    for(let term of config.level1)
                        if(item == term.name)
                            selected.push(term.category);
                }
            }

            // 根据 category 获取 series 中 data 数据项
            options.series[1].data = config.level2.filter(item => {
                return selected.includes(item.category);
            });
            options.series[2].data = config.level3.filter(item => {
                return selected.includes(item.category);
            });

            this.setOption(options);
        });

        chart.setOption({
            tooltip: {
                trigger: 'item',
                formatter: "{a} <br/>{b}: {c} ({d}%)"
            },
            legend: {
                orient: 'vertical',
                x: 'left',
                data:['师资队伍','学科建设','人才培养','科学研究','国际化程度']
            },
            series: [
                {
                    name:'一级指标',
                    type:'pie',
                    label: {
                        normal: {
                            show: false,
                        }
                    },
                    itemStyle: {
                        normal: {
                            /**
                             * 自定义饼图 扇形 颜色
                             * @param params
                             */
                            color(params) {
                                return params.data.color;
                            }
                        }
                    },
                    radius: ['15%', '30%'],
                    data: config.level1
                },
                {
                    name:'二级指标',
                    type:'pie',
                    label: {
                        normal: {
                            show: false,
                        }
                    },
                    itemStyle: {
                        normal: {
                            color(params) {
                                return params.data.color;
                            }
                        }
                    },
                    radius: ['40%', '55%'],
                    data: config.level2
                },
                {
                    name:'三级指标',
                    type:'pie',
                    radius: ['65%', '80%'],
                    itemStyle: {
                        normal: {
                            color(params) {
                                return params.data.color;
                            }
                        }
                    },
                    data: config.level3
                }
            ]
        });
	})({
        "level1": [
            {
                name: "师资队伍",
                color: "#2196F3",
                category: 0,
                value: 19
            },
            {
                name: "学科建设",
                color: "#F44336",
                category: 1,
                value: 10
            },
            {
                name: "人才培养",
                color: "#4CAF50",
                category: 2,
                value: 21
            },
            {
                name: "科学研究",
                color: "#FF9800",
                category: 3,
                value: 35
            },
            {
                name: "国际化程度",
                color: "#9C27B0",
                category: 4,
                value: 6
            }
        ],
        "level2": [
            {
                name: "基本情况",
                color: "#2196F3",
                category: 0,
                value: 3
            },
            {
                name: "师资结构",
                color: "#E3F2FD",
                category: 0,
                value: 6
            },
            {
                name: "师资水平",
                color: "#BBDEFB",
                category: 0,
                value: 10
            },
            {
                name: "学科基础",
                color: "#F44336",
                category: 1,
                value: 7
            },
            {
                name: "学科水平",
                color: "#FFEBEE",
                category: 1,
                value: 3
            },
            {
                name: "基本情况",
                color: "#4CAF50",
                category: 2,
                value: 4
            },
            {
                name: "培养条件",
                color: "#E8F5E9",
                category: 2,
                value: 7
            },
            {
                name: "培养结果",
                color: "#C8E6C9",
                category: 2,
                value: 10
            },
            {
                name: "科研条件",
                color: "#FFF3E0",
                category: 3,
                value: 2
            },
            {
                name: "科研项目",
                color: "#FFE0B2",
                category: 3,
                value: 10
            },
            {
                name: "科研论文",
                color: "#FFCC80",
                category: 3,
                value: 11
            },
            {
                name: "科研获奖",
                color: "#FFB74D",
                category: 3,
                value: 12
            },
            {
                name: "国际化人员",
                color: "#F3E5F5",
                category: 4,
                value: 2
            },
            {
                name: "合作教学",
                color: "#E1BEE7",
                category: 4,
                value: 2
            },
            {
                name: "国际化成果",
                color: "#CE93D8",
                category: 4,
                value: 2
            }
        ],
        "level3": [
            {
                name: "师资规模",
                color: "#2196F3",
                category: 0,
                value: 2
            },
            {
                name: "进修情况",
                color: "#E3F2FD",
                category: 0,
                value: 1
            },
            {
                name: "职称结构",
                color: "#BBDEFB",
                category: 0,
                value: 2
            },
            {
                name: "学历结构",
                color: "#90CAF9",
                category: 0,
                value: 1
            },
            {
                name: "学缘结构",
                color: "#64B5F6",
                category: 0,
                value: 3
            },
            {
                name: "资深学术权威",
                color: "#42A5F5",
                category: 0,
                value: 2
            },
            {
                name: "中年领军专家",
                color: "#2196F3",
                category: 0,
                value: 2
            },
            {
                name: "青年拔尖英才",
                color: "#1E88E5",
                category: 0,
                value: 4
            },
            {
                name: "国际知名学者",
                color: "#1976D2",
                category: 0,
                value: 2
            },
            {
                name: "建设基础",
                color: "#F44336",
                category: 1,
                value: 2
            },
            {
                name: "建设强度",
                color: "#FFEBEE",
                category: 1,
                value: 2
            },
            {
                name: "学科层次",
                color: "#FFCDD2",
                category: 1,
                value: 3
            },
            {
                name: "学科排名",
                color: "#EF9A9A",
                category: 1,
                value: 2
            },
            {
                name: "学科竞争力",
                color: "#E57373",
                category: 1,
                value: 1
            },
            {
                name: "研究生培养规模",
                color: "#4CAF50",
                category: 2,
                value: 3
            },
            {
                name: "培养层次",
                color: "#E8F5E9",
                category: 2,
                value: 1
            },
            {
                name: "课程资源",
                color: "#C8E6C9",
                category: 2,
                value: 4
            },
            {
                name: "教授任课情况",
                color: "#A5D6A7",
                category: 2,
                value: 3
            },
            {
                name: "教学成果",
                color: "#81C784",
                category: 2,
                value: 5
            },
            {
                name: "毕业生就业情况",
                color: "#66BB6A",
                category: 2,
                value: 1
            },
            {
                name: "造就学术人才",
                color: "#4CAF50",
                category: 2,
                value: 4
            },
            {
                name: "科研经费",
                color: "#FFF3E0",
                category: 3,
                value: 2
            },
            {
                name: "重大重点项目",
                color: "#FFE0B2",
                category: 3,
                value: 6
            },
            {
                name: "一般青年项目",
                color: "#FFCC80",
                category: 3,
                value: 4
            },
            {
                name: "中文期刊论文",
                color: "#FFB74D",
                category: 3,
                value: 1
            },
            {
                name: "中文顶尖期刊论文",
                color: "#FFA726",
                category: 3,
                value: 1
            },
            {
                name: "国际期刊论文",
                color: "#FF9800",
                category: 3,
                value: 5
            },
            {
                name: "国际顶尖期刊论文",
                color: "#FB8C00",
                category: 3,
                value: 2
            },
            {
                name: "专著专利",
                color: "#F57C00",
                category: 3,
                value: 2
            },
            {
                name: "国际三大科技奖",
                color: "#EF6C00",
                category: 3,
                value: 7
            },
            {
                name: "社会科学重大成果",
                color: "#E65100",
                category: 3,
                value: 4
            },
            {
                name: "国际权威奖项",
                color: "#FFD180",
                category: 3,
                value: 1
            },
            {
                name: "国际化教师",
                color: "#F3E5F5",
                category: 4,
                value: 1
            },
            {
                name: "国际化学生",
                color: "#E1BEE7",
                category: 4,
                value: 1
            },
            {
                name: "合作教学",
                color: "#CE93D8",
                category: 4,
                value: 2
            },
            {
                name: "国际合作论文",
                color: "#BA68C8",
                category: 4,
                value: 2
            }
        ]
    });
</script>
</body>
</html>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器人网

工业机器人伺服结构和原理

伺服的结构是怎样的?一个最简易的伺服控制单元,就是一个伺服电机加伺服控制器,今天就来解析下伺服电机与伺服控制器。 电机动作的原理 右手螺旋法则(安培定则)——通...

3365
来自专栏程序员互动联盟

【程序员故事】搞笑篇

1、我真想开个程序员餐厅了,我当老板娘,进门时先写代码再进,一楼餐厅分C包间、java包间、linux/unix包间。搞开源软件的就坐大厅里,搞Ruby的上二楼...

2753
来自专栏大神带我来搬砖

记一次高级软件架构师的铩羽而归

前几天女朋友笔记本电脑开机后进不了系统了,鉴于我天天告诉她要用宏来处理Excel,于是耳提面命,让我来修修。当时我想,这有何难,哪有程序员修不了电脑的?正如马谡...

3508
来自专栏黑泽君的专栏

壁挂式空调漏水怎么办?如何解决?

一:安装不牢固:室内机安装膨胀螺丝未打稳,安装不牢固影响平衡,导致排水管引出一侧位置偏高,造成排水困难,从而发生空调机机体滴水现象。

994
来自专栏即时通讯技术

调皮的程序员:Linux之父雕刻在Linux内核中的故事

因为LINUX操作系统的流行,Linus 已经成为地球人都知道的名人。虽然大家可能都听过钱钟书先生的名言:“假如你吃个鸡蛋觉得味道不错,又何必认识那个下蛋的母鸡...

1204
来自专栏知晓程序

举报!这里有人,在光天化日之下聚众撸猫

但并不是每个人都有机会成为「猫奴」。这时候,你需要 「吸猫君」 ,来帮你开启「云吸猫」的生活。

812
来自专栏牛客网

19届前端实习生面经

1620
来自专栏包子铺里聊IT

[面试数据结构总结1] 牵一发而不动全身,Consistent Hashing

包子IT面试培训 助你拿到理想的offer! 有问题,问包子!Got question? Ask Baozi! Consistent Hashing 是一个经...

3544
来自专栏睿哥杂货铺

我的2017年度盘点

https://www.gitbook.com/book/riboseyim/linux-perf-master/details

2108
来自专栏生信技能树

一篇文章学会ChIP-seq分析(上)

写在前面:《一篇文章学会ChIP-seq分析(上)》《一篇文章学会ChIP-seq分析(下)》为生信菜鸟团博客相关文章合集,共九讲内容。带领你从相关文献解读、资...

2.6K6

扫码关注云+社区