echarts本身没有组织结构图的节点收缩功能,因为项目需求要用到此功能。

引入的echarts必须是2版本的,因为3.0取消了对组织结构图的支持。下载2版本的源码,找到关于onclick事件那部分的代码,修改如下:

  1. _onclick: function (param) {
  2. callChartListMethodReverse(this, 'onclick', param);
  3. if (param.target) {
  4. var ecData = this._eventPackage(param.target);
  5. var option = this.getOption();
  6. var myChart = this;
  7. if (ecData && ecData.seriesIndex != null) {
  8. this._messageCenter.dispatch(ecConfig.EVENT.CLICK, param.event, ecData, this);
  9. debugger;
  10. //实现tree点击收缩
  11. a(ecData, option, myChart);
  12. }
  13. }
  14. }

建一个新文件node_contraction.js,添加如下代码:

  1. /**
  2. * menglinanke
  3. * 2017-06-12
  4. * 注释只写了第一层,里面几层均相同
  5. * 此js的前提是数据中name必须唯一,因为是根据name加以判断的。
  6. * 目前只实现到第六层(包括root),可扩充
  7. * 下面所有注释的代码供调试使用
  8. * 未使用递归,是因为本人觉得使用递归在操作(增删)data数据的时候,会出现问题(未测)
  9. * 如有大神有其他简单办法,希望告诉我一下。
  10. *
  11. */
  12. var clickMap={};//用来存储子节点(供收缩,打开节点使用)
  13. //点击时 调用
  14. function a(ecData, option, myChart){
  15. debugger;
  16. var _name = ecData.name;//当前点击节点的名称
  17. if(_posarr){
  18. var _posarr=null;
  19. }
  20. var _posarr_=_posarr;//所有老节点的信息{[name,x,y],[name,x,y]..}//貌似没啥用
  21.  
  22. // for(var iii= 0 ; iii<_posarr_.length;iii++){
  23. // alert(_posarr_[iii]);
  24. // }
  25.  
  26. var isChild=ecData.data.children;//是否存在子节点
  27. //alert(!(!isChild));
  28. var _option=option;
  29. var len1=_option.series[0].data.length;
  30. var d1=_option.series[0].data;//所有的d*在下面代码中均为使用到。
  31. var f=false;//是否找到对应节点【循环所有数据,查找到 be clicked node 在option中的位置】//----f=true.跳出所有循环
  32. //循环clickMap中所有的节点信息
  33. //for(var prop in clickMap){
  34. // if(clickMap.hasOwnProperty(prop)){
  35. // alert(prop+'-'+clickMap[prop]);
  36. // }
  37. //}
  38. //开始循环_option中的信息,用来查找当前点击的节点
  39. for(var j=0;j<len1;j++){
  40. //alert('d1[j].name='+d1[j].name);
  41. //第一个节点不让关闭(收起)
  42. if(_option.series[0].data[j].name==_name){
  43. alert('can\'t be closed.');
  44. break;
  45. }
  46. //alert(d1[j].children);
  47. if(_option.series[0].data[j].children){//若存在子节点
  48. var len2=_option.series[0].data[j].children.length;
  49. var d2=_option.series[0].data[j].children;
  50. for(var k=0;k<len2;k++){
  51. //alert('j:'+j+'--k:'+k+'-'+d2[k].name);
  52. //根据name判断节点是否是当前所点击的节点,
  53. if(_option.series[0].data[j].children[k].name==_name){
  54. //判断该节点是否已关闭,若clickMap中存在k为当前节点名称的数据,并且不为空。则说明已关闭,要打开。
  55. if(clickMap.hasOwnProperty(_name) && clickMap[_name]!=null){
  56. //alert(_name+' has closed . open now.');
  57. //将clickMap中的该节点的子节点信息重新赋值给当前节点
  58. _option.series[0].data[j].children[k].children=clickMap[_name];
  59. clickMap[_name]=null;//成功打开后,将clickMap中的数据赋null
  60. f=true;
  61. //跳出所有循环。
  62. break;
  63. }
  64. //执行到这里,说明未关闭。执行关闭操作
  65. f=true;
  66. //若所点击的节点存在子节点,则
  67. if(_option.series[0].data[j].children[k].children){
  68. //将子节点信息存入clickMap,形式【当前点击节点的name为key,子节点数据为value】
  69. clickMap[_option.series[0].data[j].children[k].name]=_option.series[0].data[j].children[k].children;
  70. //然后将_option中的当前子节点删除。
  71. delete _option.series[0].data[j].children[k].children;
  72. }
  73. //alert('find the node.j='+j+';k='+k);
  74.  
  75. //跳出所有循环
  76. break;
  77. }//else{alert(' not find the node.j='+j+';k='+k);}
  78. if(f)break;
  79. if(_option.series[0].data[j].children[k].children){
  80. var len3=_option.series[0].data[j].children[k].children.length;
  81. var d3=_option.series[0].data[j].children[k].children;
  82. for(var l=0;l<len3;l++){
  83. //alert('j:'+j+'--k:'+k+'--l:'+l+'-'+d3[l].name);
  84. if(_option.series[0].data[j].children[k].children[l].name==_name){
  85. if(clickMap.hasOwnProperty(_name) && clickMap[_name]!=null){
  86. //alert(_name+'has closed . open now.');
  87. _option.series[0].data[j].children[k].children[l].children=clickMap[_name];
  88. clickMap[_name]=null;
  89. f=true;
  90. break;
  91. }
  92. f=true;
  93. //alert('find the node.j='+j+';k='+k+';l='+l+'--'+_option.series[0].data[j].children[k].children[l].name);
  94. if(_option.series[0].data[j].children[k].children[l].children){
  95. clickMap[_option.series[0].data[j].children[k].children[l].name]=_option.series[0].data[j].children[k].children[l].children;
  96. delete _option.series[0].data[j].children[k].children[l].children;
  97. }
  98. break;
  99. }//else{alert(' not find the node.j='+j+';k='+k+';l='+l+'--'+d3[l].name);}
  100. if(f)break;
  101. if(_option.series[0].data[j].children[k].children[l].children){
  102. var len4=_option.series[0].data[j].children[k].children[l].children.length;
  103. var d4=_option.series[0].data[j].children[k].children[l].children;
  104. for(var m=0;m<len4;m++){
  105. if(_option.series[0].data[j].children[k].children[l].children[m].name==_name){
  106. if(clickMap.hasOwnProperty(_name) && clickMap[_name]!=null){
  107. //alert(_name+'has closed . open now.');
  108. _option.series[0].data[j].children[k].children[l].children[m].children=clickMap[_name];
  109. clickMap[_name]=null;
  110. f=true;
  111. break;
  112. }
  113. f=true;
  114. //alert('find the node.j='+j+';k='+k+';l='+l+';m='+m+'--'+_option.series[0].data[j].children[k].children[l].children[m].name);
  115. if(_option.series[0].data[j].children[k].children[l].children[m].children){
  116. clickMap[_option.series[0].data[j].children[k].children[l].children[m].name]=_option.series[0].data[j].children[k].children[l].children[m].children;
  117. delete _option.series[0].data[j].children[k].children[l].children[m].children;
  118. }
  119. break;
  120. }//else{alert(' not find the node.j='+j+';k='+k+';l='+l+';m='+m+'--'+d4[m].name);}
  121. if(f)break;
  122. if(_option.series[0].data[j].children[k].children[l].children[m].children){
  123. var len5=_option.series[0].data[j].children[k].children[l].children[m].children.length;
  124. var d5=_option.series[0].data[j].children[k].children[l].children[m].children;
  125. for(var n = 0 ; n<len5;n++){
  126. /**
  127. * 最后一层循环
  128. * 若有需要,可扩充
  129. */
  130. if(_option.series[0].data[j].children[k].children[l].children[m].children[n].name==_name){
  131. if(clickMap.hasOwnProperty(_name)&&clickMap[_name]!=null){
  132. //alert(_name+'has closed . open now.');
  133. _option.series[0].data[j].children[k].children[l].children[m].children[n].children=clickMap[_name];
  134. clickMap[_name]=null;
  135. f=true;
  136. break;
  137. }
  138. f=true;
  139. //alert('find the final node .'+_option.series[0].data[j].children[k].children[l].children[m].children[n].name);
  140. if(_option.series[0].data[j].children[k].children[l].children[m].children[n].children){
  141. clickMap[_option.series[0].data[j].children[k].children[l].children[m].children[n].name]=_option.series[0].data[j].children[k].children[l].children[m].children[n].children;
  142. delete _option.series[0].data[j].children[k].children[l].children[m].children[n].children;
  143. }
  144. break;
  145. }//else{alert(' not find the final node .'+d5[n].name);}
  146. if(f)break;
  147. }
  148. }//else{alert('d4[m]:'+d4[m].name +'-下没有子级');}
  149. if(f)break;
  150. }
  151. }//else{alert('d3[l]:'+d3[l].name+'-没有子级');}
  152. if(f)break;
  153. }
  154. }//else{alert('d2[k]:'+d2[k].name+'没有子级');}
  155. if(f)break;
  156. }
  157. }//else{alert('d1[j]:'+d1[j].name+'下没有子级');}
  158. if(f)break;
  159. }
  160. //alert('over.');
  161. //清空当前echarts
  162. myChart.clear();
  163. //重新赋值,渲染图表
  164. myChart.setOption(_option);
  165. // _posarr_=_posarr;//新的坐标???//待开发功能。
  166. // for(var ii= 0 ; ii<_posarr_.length;ii++){
  167. // alert(_posarr_[ii]);
  168. // }
  169. //刷新,没啥用。。
  170. myChart.refresh();
  171. //for(var i=0;i<_posarr_.length;i++){
  172. // if(_name==_posarr_[i][0]){
  173. // alert('当前点击:'+_posarr_[i]);
  174. // break;
  175. // }
  176. //}
  177. }

然后在需要的地方引入这个文件就可以了。

实现原理:
1:定义一个array存放子节点信息。【样式  [父节点name,子节点]】
2:循环所有data中的数据,找到当前点击的节点
(if:1)根据父节点name,判断array中是否存在该节点数据,若存在并且不为空,则将该子节点数据赋值于该节点,然后将array中的该子节点信息赋值为null,跳出所有循环。重新渲染图表
(if:2)(array中不存在该节点信息的前提下)若该节点存在子节点,则将子节点按照 [父节点 name,子节点] 的样式,将子节点信息存入map,然后删除data中的该节点的子节点。跳出所有循环,重新渲染图表。
难点:
1:循环所有data数据。不能使用值引用,这样的话在删除(添加)子节点信息的时候,渲染数据的最终data起不到任何作用。(本人是使用原data,一级一级点下来的)
2:子节点数据的保存及删除。这里定义的array实现的功能类似java里的map,删除json中的数据使用delete。(delete data[0].children;)
3:重新渲染。setOption之前先clear一下。

如何实现echarts组织结构图节点的收缩的更多相关文章

  1. dhtmlxtree 节点 展开收缩:新增了直接点 文本内容 也 实现了 展开收缩 功能(并记住了展开、收缩状态)

    dhtmlxtree 节点 展开收缩通常情况我们按 +- 就实现了 展开收缩 功能,为了方便我们新增了直接点 文本内容 也 实现了 展开收缩 功能(并记住了展开.收缩状态) tree = new dh ...

  2. ECharts树图节点过多时取消缩放,调整容器高度自适应内容变化

    问题现象 使用ECharts树图,在数据维度大,节点过多时,所看到的内容会重叠交错,无法查看. 原因 在给定ECharts树图容器尺寸后,无论数据多么庞大或者稀少,数据始终会尝试在给定容器内撑满.全部 ...

  3. DataGridView之行的展开与收缩

    很多数据都有父节点与子节点,我们希望单击父节点的时候可以展开父节点下的子节点数据. 比如一个医院科室表,有父科室与子科室,点击父科室后,在父科室下面可以展现该科室下的所有子科室. 我们来说一下在Dat ...

  4. echarts map 地图在react项目中的使用

    需求 展示海南省地图,点击市高亮展示,并在右侧展示对应市的相关数据. 准备工作 Echarts 海南地图json 效果图 代码 index.tsx import React, { useRef, us ...

  5. 1122从业务优化MYSQL

    http://blog.itpub.net/22664653/viewspace-2079576/ 开发反馈一个表的数据大小已经130G,对物理存储空间有影响,且不容易做数据库ddl变更.咨询了开发相 ...

  6. Winform开发主界面菜单的动态树形列表展示

    我在之前很多文章里面,介绍过Winform主界面的开发,基本上都是标准的界面,在顶部放置工具栏,中间区域则放置多文档的内容,但是在顶部菜单比较多的时候,就需要把菜单分为几级处理,如可以在顶部菜单放置一 ...

  7. jquery easy ui 1.3.4 Tree树形菜单(9)

    9.1.创建树形菜单 <ul id="tt" class="easyui-tree"> <li><span>第一级</ ...

  8. Android无限级树状结构

    通过对ListView简单的扩展.再封装,即可实现无限层级的树控件TreeView. package cn.asiontang.nleveltreelistview; import android.a ...

  9. CTreeCtrl 控件总结

      一 基础操作  1 插入节点 1)插入根节点 //插入根节点 HTREEITEM hRoot; CString str=L"ROOT" hRoot=nTreeCtrl.Inse ...

随机推荐

  1. CentOS7编译安装sshpass过程

    环境说明:centos 7 cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) 我的sshpass版本 sshpass-1.06. ...

  2. java 异常体系详细介绍

    一.异常概述与异常体系结构 异常:在Java语言中,将程序执行中发生的不正常情况称为"异常".(开发过程中的语法错误和逻辑错误不是异常). Java把异常当作对象来处理,并定义一个 ...

  3. 数位DP 计划

    通常的数位dp可以写成如下形式: [cpp] view plain copy int dfs(int i, int s, bool e) { if (i==-1) return s==target_s ...

  4. Scrapy 教程(七)-架构与中间件

    Scrapy 使用 Twisted 这个异步框架来处理网络通信,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求. Scrapy 架构 其实之前的教程都有涉及,这里再做个系统介绍 Engin ...

  5. 2019 安洵杯 Re 部分WP

    0x01.EasyEncryption 测试文件:https://www.lanzous.com/i7soysb 1.IDA打开 int sub_416560() { int v0; // eax i ...

  6. css水平垂直居中问题

    水平居中: 行内元素:text-align:center; 块级元素:magin:0 auto; 子元素设置:position:absolute;  left:50%;  transform:tran ...

  7. vue图片不存在时加载默认图片

    在文件中的img那里添加:οnerrοr="errorImg01",然后设置errorImg01的路径如果直接写成 errorImg01: ('../../assets/image ...

  8. C++函数声明与定义

    一个C++函数,如果没有函数声明而只有函数定义,程序照样运行,但要求这个函数定义必须放在main函数之前,否则编译按照从上到下的顺序扫描下来,就会出现编译器不认识它的情况. 如果一个程序同时有函数声明 ...

  9. java交换两个变量值a,b的多钟方法

    首先我们定义两个变量用来检查方法可行性 int a=5; int b=3; 方法一,也是最容易想到的,就是建立中间变量法 int temp; temp=a; a=b; b=temp; System.o ...

  10. 事件,IO,select

    事件驱动模型 对于普通编程来说,代码遵循线性流程:开始-->代码A-->代码B-->代码C-->...-->结束,编程者知道代码的运行顺序,由编程者控制 事件驱动模型,流 ...