Echarts可视化开发之树型图(公司人事架构图)

引言:Echarts是百度开发的一款可视化的开源js框架,诸如此类的框架很多,今天我们就重点研究Echarts。使用Echarts非常简单,我们将需要展示的数据源以及可视化效果以参数的形式传入Echarts中即可。

一.Echarts使用

我们以官网的一个关于制作简单的树形图为例子,说明Echarts开发的整套流程。

1.开发流程

1).编写visual.hmtl文件,并引入echarts.js文件。

我们这里使用的是echarts 2.x版本,因为3.x版本中tree结构被移除了。详情见echarts配置及下载官方文档

2).定义一个容器

我们将可视化展示的图形放在一个定制好的容器中,这里所说的容器是div或者 可以容纳其他元素的便签。

3).配置数据源和参数

通过echarts提供的接口配置我们需要展示的数据源和效果

2.demo程序

1)效果展示如下:


2)核心代码如下:

  1. <html>  
  2. <head>  
  3.   <meta charset="UTF-8">  
  4. <title>社交网络</title>  
  5.  <style>  
  6. </style>  
  7.    <script src="echarts-2.x.js"></script>  
  8.    </head>  
  9.   <body>  
  10.     <!-- 为ECharts准备一个具备大小(宽高)的Dom -->  
  11.    <div style="padding:20px;width:100%;height:100%;">   
  12.                <div id="main" style="width: 1104px;height:464px;">  
  13.                </div>  
  14.  </div>  
  15.     <script type="text/javascript">  
  16.     //定义echarts容器  
  17.     var myChart = echarts.init(document.getElementById('main'), 'macarons');  
  18.     option = {  
  19.     title : {  
  20.         text: '手机品牌',  
  21.         subtext: '线、节点样式'  
  22.     },  
  23.     series : [  
  24.         {  
  25.             name:'树图',  
  26.             type:'tree',  
  27.             orient: 'horizontal',  // vertical horizontal  
  28.             rootLocation: {x: 100, y: '60%'}, // 根节点位置  {x: 'center',y: 10}  
  29.             nodePadding: 20,  
  30.             symbol: 'circle',  
  31.             symbolSize: 40,  
  32.             itemStyle: {  
  33.                 normal: {  
  34.                     label: {  
  35.                         show: true,  
  36.                         position: 'inside',  
  37.                         textStyle: {  
  38.                             color: '#cc9999',  
  39.                             fontSize: 15,  
  40.                             fontWeight:  'bolder'  
  41.                         }  
  42.                     },  
  43.                     lineStyle: {  
  44.                         color: '#000',  
  45.                         width: 1,  
  46.                         type: 'broken' // 'curve'|'broken'|'solid'|'dotted'|'dashed'  
  47.                     }  
  48.                 },  
  49.                 emphasis: {  
  50.                     label: {  
  51.                         show: true  
  52.                     }  
  53.                 }  
  54.             },  
  55.             data: [  
  56.                 {  
  57.                     name: '手机',  
  58.                     value: 6,  
  59.                     symbolSize: [90, 70],  
  60.                     symbol: 'image://http://www.iconpng.com/png/ecommerce-business/iphone.png',  
  61.                     itemStyle: {  
  62.                         normal: {  
  63.                             label: {  
  64.                                 show: false  
  65.                             }  
  66.                         }  
  67.                     },  
  68.                     children: [  
  69.                         {  
  70.                             name: '小米',  
  71.                             value: 4,  
  72.                             symbol: 'image://http://pic.58pic.com/58pic/12/36/51/66d58PICMUV.jpg',  
  73.                             itemStyle: {  
  74.                                 normal: {  
  75.                                     label: {  
  76.                                         show: false  
  77.                                     }  
  78.                                 }  
  79.                             },  
  80.                             symbolSize: [60, 60],  
  81.                             children: [  
  82.                                 {  
  83.                                     name: '小米1',  
  84.                                     symbol: 'circle',  
  85.                                     symbolSize: 20,  
  86.                                     value: 4,  
  87.                                     itemStyle: {  
  88.                                         normal: {  
  89.                                             color: '#fa6900',  
  90.                                             label: {  
  91.                                                 show: true,  
  92.                                                 position: 'right'  
  93.                                             },  
  94.                                               
  95.                                         },  
  96.                                         emphasis: {  
  97.                                             label: {  
  98.                                                 show: false  
  99.                                             },  
  100.                                             borderWidth: 0  
  101.                                         }  
  102.                                     }  
  103.                                 },  
  104.                                 {  
  105.                                     name: '小米2',  
  106.                                     value: 4,  
  107.                                     symbol: 'circle',  
  108.                                     symbolSize: 20,  
  109.                                     itemStyle: {  
  110.                                         normal: {  
  111.                                             label: {  
  112.                                                 show: true,  
  113.                                                 position: 'right',  
  114.                                                 formatter: "{b}"  
  115.                                             },  
  116.                                             color: '#fa6900',  
  117.                                             borderWidth: 2,  
  118.                                             borderColor: '#cc66ff'  
  119.   
  120.                                         },  
  121.                                         emphasis: {  
  122.                                             borderWidth: 0  
  123.                                         }  
  124.                                     }  
  125.                                 },  
  126.                                 {  
  127.                                     name: '小米3',  
  128.                                     value: 2,  
  129.                                     symbol: 'circle',  
  130.                                     symbolSize: 20,  
  131.                                     itemStyle: {  
  132.                                         normal: {  
  133.                                             label: {  
  134.                                                 position: 'right'  
  135.                                             },  
  136.                                             color: '#fa6900',  
  137.                                             brushType: 'stroke',  
  138.                                             borderWidth: 1,  
  139.                                             borderColor: '#999966',  
  140.                                         },  
  141.                                         emphasis: {  
  142.                                             borderWidth: 0  
  143.                                         }  
  144.                                     }  
  145.                                 }  
  146.                             ]  
  147.                         },  
  148.                         {  
  149.                             name: '苹果',  
  150.                             symbol: 'image://http://www.viastreaming.com/images/apple_logo2.png',  
  151.                             symbolSize: [60, 60],  
  152.                             itemStyle: {  
  153.                                 normal: {  
  154.                                     label: {  
  155.                                         show: false  
  156.                                     }  
  157.                                       
  158.                                 }  
  159.                             },  
  160.                             value: 4  
  161.                         },  
  162.                         {  
  163.                             name: '华为',  
  164.                             symbol: 'image://http://market.huawei.com/hwgg/logo_cn/download/logo.jpg',  
  165.                             symbolSize: [60, 60],  
  166.                             itemStyle: {  
  167.                                 normal: {  
  168.                                     label: {  
  169.                                         show: false  
  170.                                     }  
  171.                                       
  172.                                 }  
  173.                             },  
  174.                             value: 2  
  175.                         },  
  176.                         {  
  177.                             name: '联想',  
  178.                             symbol: 'image://http://www.lenovo.com.cn/HomeUpload/Home001/6d94ee9a20140714.jpg',  
  179.                             symbolSize: [100, 40],  
  180.                             itemStyle: {  
  181.                                 normal: {  
  182.                                     label: {  
  183.                                         show: false  
  184.                                     }  
  185.                                       
  186.                                 }  
  187.                             },  
  188.                             value: 2  
  189.                         }  
  190.                     ]  
  191.                 }  
  192.             ]  
  193.         }  
  194.     ]  
  195. };               
  196.  myChart.setOption(option);  
  197.   </script>        
  198.   </body>  
  199. </html>  

完整demo程序下载


二.根据不同数据源,定制开发tree图

我们从上面的demo程序中知道画树型图重点在于如何描述数据,上面配置参数里的data形式如下

data是一个数组形式,它是用来表示多个数据源,由于我们这里只需要使用一个数据源。所以我们只要提供类似{}结构的一个对象即可。即[{根对象}],我们这里只简单使用了name和children属性来说明问题。

  1. [{name:"根",children:[             
  2. {"name":"子根1",children:[...]},  
  3. {"{"name":"子根2",children:[...]}  
  4. {"name":"子根3",children:[....]},  
  5. ]}]  
我们从这里不难看出这里是一个递归结构的数据形式。所以重点是把我们定义的数据源能够转化成这样的一种形式。
我们对数据源进行分层,即建立父子关系。

数据源形式可以如下

  1.      var zNodes=[  
  2.     {id:1,pId:0,name:"董事长"},  
  3.     {id:11,pId:1,name:"经理"},  
  4.     {id:12,pId:1,name:"副总"},  
  5.     {id:13,pId:1,name:"秘书"},  
  6.     {id:16,pId:11,name:"财务经理"},  
  7.     {id:27,pId:11,name:"人事经理"},  
  8.     {id:18,pId:12,name:"HR"},  
  9. ]  
1.建立每个节点到对应子节点列表的映射,即groups对象结构,里面存放着每个节点id和对应子节点的映射
  1. groups={}  
  2. for(var i=0;i<zNodes.length;i++){  
  3. var pid=zNodes[i]['pId']  
  4. //如果该pid对应组不存在  
  5. if(!groups[pid])  
  6. groups[pid]=[]  
  7. //添加子节点  
  8. groups[pid].push(zNodes[i])  
  9. }  
2.从根节点开始构建tree树需要的数据结构,这里是一个递归函数的应用,递归函数的三个重要的点在于结束条件,向下传递的表达式,向上返回的表达式。即结束条件和递归表达式。递归其实是将一个大问题分解成若干相似的小问题来解决。我思考这个问题时从以下2个点进行考虑:

1)结束条件以及此时返回的值。

如果某节点下不存在子节点则返回,不在继续递归下去。此时返回该节点的信息

2)抽象程序的流程。

其实针对这类树问题,我们可以将其变成树和子树的关系来考虑,其实就是构建根节点下的各个子树的数据,而子树的结构同样也是构建以该子树为跟的子树的结构。这里其实就是一个树的递归的定义过程。

描述如下:

//以根节点id为入口

  1. function rescusive(number){  
  2. //根节点  
  3. var node={}  
  4. //存放子树  
  5. var data=[]  
  6. childrenList=groups[number]  
  7. //如果不存在子节点,这里其实就是结束条件  
  8. if(!childenList||childrenList.length==0){  
  9. node['name']=number;  
  10. node['children']=[]  
  11. return node;  
  12. }  
  13. for(var i=0;i<childrenList.length;i++){  
  14. //递归该节点下的子树来建构该子树  
  15. var children=rescusive(childrenList[i]["id"])  
  16. //将该子树加入根节点中  
  17. data.push(children)  
  18. }  
  19. node['name']=number  
  20. //根节点中的子树集合  
  21. node['children']=data  
  22. return node  
  23. }  

3.构建tree数据

下面我们通过整合以上代码,通过面向对象编程的思想进行完成构建该对象

1)TreeGraph.js文件内容如下:

  1. function treeMenu(a){  
  2.     //列表map形式  
  3.     this.tree=a||[];  
  4.     this.groups={};  
  5.     //存放id与对应的name映射  
  6.     this.nameMap={}  
  7.     //得到每个点对应的层次,为了后期进行布局  
  8.     this.levelMap={}  
  9.     //样式设计  
  10.     this.style={"symbolSize":[60,50,40,30,20],"value":[8,6,4,2,1]}  
  11. };  
  12. treeMenu.prototype={  
  13.     init:function(pid){  
  14.         this.group();  
  15.         this.MapNamebyId();  
  16.         this.setIdLevel(pid);  
  17.         return this.rescusive(pid);  
  18.     },  
  19.     group:function(){  
  20.         for(var i=0;i<this.tree.length;i++){  
  21.             //存在该grops则直接添加  
  22.             if(this.groups[this.tree[i].pId]){  
  23.                 this.groups[this.tree[i].pId].push(this.tree[i]);  
  24.             }else{  
  25.                 this.groups[this.tree[i].pId]=[];  
  26.                 this.groups[this.tree[i].pId].push(this.tree[i]);  
  27.             }  
  28.         }  
  29.     },  
  30.     //得到每个点的层次  
  31.     setIdLevel:function(pid){  
  32.         var level=1;  
  33.         this.levelMap[pid]=level;  
  34.         var gs=this.groups[pid];  
  35.         //str=JSON.stringify(gs)  
  36.         //alert("json:"+str)  
  37.         var temp=[]  
  38.         while(gs){  
  39.             level++;  
  40.             if(gs==null||gs==undefined||gs.length==0)  
  41.                 break;  
  42.             temp=[]  
  43.             for(var i=0;i<gs.length;i++){  
  44.                 var myid=gs[i]["id"];  
  45.                 this.levelMap[myid]=level;  
  46.                 subgs=this.groups[myid];  
  47.                 if(subgs instanceof Array &&subgs!=null){  
  48.                 for(var j=0;j<subgs.length;j++){  
  49.                 temp.push(subgs[j]);  
  50.                 }  
  51.                 }  
  52.             }  
  53.             gs=temp;  
  54.         }  
  55.           
  56.     },  
  57.     //根据所在层次设计不同大小的样式  
  58.     getStyleById:function(id){  
  59.         var level=this.levelMap[id]  
  60.         if(level>=5)  
  61.             level=5;  
  62.         var symbolize=0  
  63.         var value=0  
  64.         symbolize=this.style['symbolSize'][level-1]  
  65.         value=this.style['value'][level-1]  
  66.         var styleValue={}  
  67.         styleValue['symbolSize']=symbolize  
  68.         styleValue['value']=value  
  69.         return styleValue  
  70.     },  
  71.     MapNamebyId:function(){  
  72.         for(var i=0;i<this.tree.length;i++){  
  73.             map=this.tree[i]  
  74.             this.nameMap[map["id"]]=map["name"]  
  75.         }  
  76.     },  
  77.     //设置节点属性  
  78.     setNode:function(node,name,symbolize,value,children){  
  79.             node['name']=name;  
  80.             node['symbolSize']=symbolize;  
  81.             node['value']=value  
  82.             node['children']=children  
  83.             return node;  
  84.     },  
  85.     <span style="color:#ff0000;">rescusive:function (number){//这里是构建数据源的重点</span>  
  86.         var data=[]  
  87.         var node={}  
  88.         var styleValue={}  
  89.         //某个节点下的子节点  
  90.         var a=this.groups[number];  
  91.         var nodeName=this.nameMap[number];  
  92.         if(a==null||a==undefined){  
  93.             styleValue=this.getStyleById(number)  
  94.             //设置节点  
  95.             this.setNode(node,nodeName,styleValue['symbolSize'],styleValue['value'],[])  
  96.             return node;  
  97.         }  
  98.         for(var i=0;i<a.length;i++){  
  99.             children=this.rescusive(a[i].id);  
  100.             data.push(children);  
  101.         }  
  102.         styleValue=this.getStyleById(number)  
  103.         this.setNode(node,nodeName,styleValue['symbolSize'],styleValue['value'],data)  
  104.         return node;  
  105.     },  
  106.     //创建组织结构图  
  107.     createTreeVisual:function(myChart,title,data){  
  108.         var option = {  
  109.         title : {  
  110.         text: title  
  111.        },  
  112.         tooltip : {  
  113.         trigger: 'item',  
  114.         formatter: "{b}"  
  115.         },  
  116.       toolbox: {  
  117.         show : true,  
  118.         feature : {  
  119.             saveAsImage : {show: true}  
  120.          }  
  121.       },  
  122.       calculable : false,  
  123.        series : [  
  124.          {  
  125.             name:'树图',  
  126.             type:'tree',  
  127.             orient: 'horizontal',  // vertical horizontal  
  128.             rootLocation: {x: 100, y: '60%'}, // 根节点位置  {x: 'center',y: 10}  
  129.             nodePadding: 20,  
  130.             symbol: 'circle',  
  131.             data:data  
  132.         }]//series  
  133.     }     
  134.      myChart.setOption(option);  
  135.     }  
  136. }  
  137. //得到数据  
  138. function getData(zNodes){  
  139.     var mytree=new treeMenu(zNodes)  
  140.     treeData=mytree.init(0)  
  141.     data=[]  
  142.     data.push(treeData)  
  143.     return data;  
  144.     //str=JSON.stringify(menu);  
  145.     //alert("responsing json:"+str)  
  146. }  
  147. function createTreeV(mychart,title,znodes){  
  148.     var mytree=new treeMenu(znodes)  
  149.     treeData=mytree.init(1)  
  150.     data=[]  
  151.     data.push(treeData)  
  152.     mytree.createTreeVisual(myChart,title,data)  
  153. }  
2) html页面代码如下:
  1. <html>  
  2. <head>  
  3.   <meta charset="UTF-8">  
  4. <title>社交网络</title>  
  5. </style>  
  6.   
  7.    <script src="echarts-2.x.js"></script>  
  8.     <script src="TreeGraph.js"></script>  
  9.     
  10.    </head>  
  11.   <body>  
  12.     <!-- 为ECharts准备一个具备大小(宽高)的Dom -->  
  13.    <div style="padding:20px;width:100%;height:100%;">   
  14.   
  15.         <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->  
  16.                <div id="main" style="width: 1104px;height:464px;">  
  17.                    
  18.                </div>  
  19.              
  20.       <div id='main_1' style="position: relative;height:15px;width: 100%;color:#A52A2A"></div>  
  21.             
  22.  </div>  
  23.     <script type="text/javascript">  
  24.    //data  
  25.     //data=createDatabyHand()  
  26.     var zNodes=[  
  27.     {id:1,pId:0,name:"董事长"},  
  28.     {id:11,pId:1,name:"经理"},  
  29.     {id:12,pId:1,name:"副总"},  
  30.     {id:13,pId:1,name:"秘书"},  
  31.     {id:16,pId:11,name:"财务经理"},  
  32.     {id:27,pId:11,name:"人事经理"},  
  33.     {id:18,pId:12,name:"HR"},  
  34.     ]  
  35.     data=getData(zNodes)  
  36.     var myChart = echarts.init(document.getElementById('main'), 'macarons');  
  37.     createTreeV(myChart,"人事架构图",zNodes)  
  38.      
  39.   </script>        
  40.   </body>  
  41. </html>  
3)页面效果如下:


4)完整代码及echart.js下载见可视化树图完整代码

三 .总结

基础知识很重要,之前对于递归虽然有所了解,但是理解不深。通过这次实践加深了对递归的理解和应用。关于echarts可视化这块,重点学习如何插入数据源和修改样式。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值