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

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

_onclick: function (param) {
callChartListMethodReverse(this, 'onclick', param);
if (param.target) {
var ecData = this._eventPackage(param.target);
var option = this.getOption();
var myChart = this;
if (ecData && ecData.seriesIndex != null) {
this._messageCenter.dispatch(ecConfig.EVENT.CLICK, param.event, ecData, this);
debugger;
//实现tree点击收缩
a(ecData, option, myChart);
}
}
}

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

/**
* menglinanke
* 2017-06-12
* 注释只写了第一层,里面几层均相同
* 此js的前提是数据中name必须唯一,因为是根据name加以判断的。
* 目前只实现到第六层(包括root),可扩充
* 下面所有注释的代码供调试使用
* 未使用递归,是因为本人觉得使用递归在操作(增删)data数据的时候,会出现问题(未测)
* 如有大神有其他简单办法,希望告诉我一下。
*
*/
var clickMap={};//用来存储子节点(供收缩,打开节点使用)
//点击时 调用
function a(ecData, option, myChart){
debugger;
var _name = ecData.name;//当前点击节点的名称
if(_posarr){
var _posarr=null;
}
var _posarr_=_posarr;//所有老节点的信息{[name,x,y],[name,x,y]..}//貌似没啥用 // for(var iii= 0 ; iii<_posarr_.length;iii++){
// alert(_posarr_[iii]);
// } var isChild=ecData.data.children;//是否存在子节点
//alert(!(!isChild));
var _option=option;
var len1=_option.series[0].data.length;
var d1=_option.series[0].data;//所有的d*在下面代码中均为使用到。
var f=false;//是否找到对应节点【循环所有数据,查找到 be clicked node 在option中的位置】//----f=true.跳出所有循环
//循环clickMap中所有的节点信息
//for(var prop in clickMap){
// if(clickMap.hasOwnProperty(prop)){
// alert(prop+'-'+clickMap[prop]);
// }
//}
//开始循环_option中的信息,用来查找当前点击的节点
for(var j=0;j<len1;j++){
//alert('d1[j].name='+d1[j].name);
//第一个节点不让关闭(收起)
if(_option.series[0].data[j].name==_name){
alert('can\'t be closed.');
break;
}
//alert(d1[j].children);
if(_option.series[0].data[j].children){//若存在子节点
var len2=_option.series[0].data[j].children.length;
var d2=_option.series[0].data[j].children;
for(var k=0;k<len2;k++){
//alert('j:'+j+'--k:'+k+'-'+d2[k].name);
//根据name判断节点是否是当前所点击的节点,
if(_option.series[0].data[j].children[k].name==_name){
//判断该节点是否已关闭,若clickMap中存在k为当前节点名称的数据,并且不为空。则说明已关闭,要打开。
if(clickMap.hasOwnProperty(_name) && clickMap[_name]!=null){
//alert(_name+' has closed . open now.');
//将clickMap中的该节点的子节点信息重新赋值给当前节点
_option.series[0].data[j].children[k].children=clickMap[_name];
clickMap[_name]=null;//成功打开后,将clickMap中的数据赋null
f=true;
//跳出所有循环。
break;
}
//执行到这里,说明未关闭。执行关闭操作
f=true;
//若所点击的节点存在子节点,则
if(_option.series[0].data[j].children[k].children){
//将子节点信息存入clickMap,形式【当前点击节点的name为key,子节点数据为value】
clickMap[_option.series[0].data[j].children[k].name]=_option.series[0].data[j].children[k].children;
//然后将_option中的当前子节点删除。
delete _option.series[0].data[j].children[k].children;
}
//alert('find the node.j='+j+';k='+k); //跳出所有循环
break;
}//else{alert(' not find the node.j='+j+';k='+k);}
if(f)break;
if(_option.series[0].data[j].children[k].children){
var len3=_option.series[0].data[j].children[k].children.length;
var d3=_option.series[0].data[j].children[k].children;
for(var l=0;l<len3;l++){
//alert('j:'+j+'--k:'+k+'--l:'+l+'-'+d3[l].name);
if(_option.series[0].data[j].children[k].children[l].name==_name){
if(clickMap.hasOwnProperty(_name) && clickMap[_name]!=null){
//alert(_name+'has closed . open now.');
_option.series[0].data[j].children[k].children[l].children=clickMap[_name];
clickMap[_name]=null;
f=true;
break;
}
f=true;
//alert('find the node.j='+j+';k='+k+';l='+l+'--'+_option.series[0].data[j].children[k].children[l].name);
if(_option.series[0].data[j].children[k].children[l].children){
clickMap[_option.series[0].data[j].children[k].children[l].name]=_option.series[0].data[j].children[k].children[l].children;
delete _option.series[0].data[j].children[k].children[l].children;
}
break;
}//else{alert(' not find the node.j='+j+';k='+k+';l='+l+'--'+d3[l].name);}
if(f)break;
if(_option.series[0].data[j].children[k].children[l].children){
var len4=_option.series[0].data[j].children[k].children[l].children.length;
var d4=_option.series[0].data[j].children[k].children[l].children;
for(var m=0;m<len4;m++){
if(_option.series[0].data[j].children[k].children[l].children[m].name==_name){
if(clickMap.hasOwnProperty(_name) && clickMap[_name]!=null){
//alert(_name+'has closed . open now.');
_option.series[0].data[j].children[k].children[l].children[m].children=clickMap[_name];
clickMap[_name]=null;
f=true;
break;
}
f=true;
//alert('find the node.j='+j+';k='+k+';l='+l+';m='+m+'--'+_option.series[0].data[j].children[k].children[l].children[m].name);
if(_option.series[0].data[j].children[k].children[l].children[m].children){
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;
delete _option.series[0].data[j].children[k].children[l].children[m].children;
}
break;
}//else{alert(' not find the node.j='+j+';k='+k+';l='+l+';m='+m+'--'+d4[m].name);}
if(f)break;
if(_option.series[0].data[j].children[k].children[l].children[m].children){
var len5=_option.series[0].data[j].children[k].children[l].children[m].children.length;
var d5=_option.series[0].data[j].children[k].children[l].children[m].children;
for(var n = 0 ; n<len5;n++){
/**
* 最后一层循环
* 若有需要,可扩充
*/
if(_option.series[0].data[j].children[k].children[l].children[m].children[n].name==_name){
if(clickMap.hasOwnProperty(_name)&&clickMap[_name]!=null){
//alert(_name+'has closed . open now.');
_option.series[0].data[j].children[k].children[l].children[m].children[n].children=clickMap[_name];
clickMap[_name]=null;
f=true;
break;
}
f=true;
//alert('find the final node .'+_option.series[0].data[j].children[k].children[l].children[m].children[n].name);
if(_option.series[0].data[j].children[k].children[l].children[m].children[n].children){
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;
delete _option.series[0].data[j].children[k].children[l].children[m].children[n].children;
}
break;
}//else{alert(' not find the final node .'+d5[n].name);}
if(f)break;
}
}//else{alert('d4[m]:'+d4[m].name +'-下没有子级');}
if(f)break;
}
}//else{alert('d3[l]:'+d3[l].name+'-没有子级');}
if(f)break;
}
}//else{alert('d2[k]:'+d2[k].name+'没有子级');}
if(f)break;
}
}//else{alert('d1[j]:'+d1[j].name+'下没有子级');}
if(f)break;
}
//alert('over.');
//清空当前echarts
myChart.clear();
//重新赋值,渲染图表
myChart.setOption(_option);
// _posarr_=_posarr;//新的坐标???//待开发功能。
// for(var ii= 0 ; ii<_posarr_.length;ii++){
// alert(_posarr_[ii]);
// }
//刷新,没啥用。。
myChart.refresh();
//for(var i=0;i<_posarr_.length;i++){
// if(_name==_posarr_[i][0]){
// alert('当前点击:'+_posarr_[i]);
// break;
// }
//}
}

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

实现原理:
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. [DS+Algo] 002 一维表结构

    目录 1. 顺序表 1.1 分类 1.2 实现方式 1.3 扩容问题 1.4 操作 2. 链表 2.1 分类 2.2 链表相关操作 2.3 链表 VS 顺序表 3. 关于代码实现 1. 顺序表 1.1 ...

  2. 【监控笔记】【3.1】DML(CDC)、DDL(DDL触发器)跟踪数据更改,数据库审计

    关键词:数据库审计.DDL审计.DML审计 [监控笔记][3.1]DML(CDC).DDL(DDL触发器)跟踪数据更改 [1]DML(CDC) 2008及以上 https://www.cnblogs. ...

  3. P1168 中位数 堆

    题目描述 给出一个长度为NN的非负整数序列A_iAi​,对于所有1 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A_1, A_3, …, A_{2k - 1}A1​,A3​,…,A2 ...

  4. 目标检测(三) Fast R-CNN

    引言 之前学习了 R-CNN 和 SPPNet,这里做一下回顾和补充. 问题 R-CNN 需要对输入进行resize变换,在对大量 ROI 进行特征提取时,需要进行卷积计算,而且由于 ROI 存在重复 ...

  5. web 过滤器 Filter、 Spring 拦截器 interceptor

    1.过滤器(Filter)(在web.xml中注册过滤器) 首先说一下Filter的使用地方,我们在配置web.xml时,总会配置下面一段设置字符编码,不然会导致乱码问题: <filter> ...

  6. MySQL 的自增 ID 用完了,怎么办?

      一.简述 在 MySQL 中用很多类型的自增 ID,每个自增 ID 都设置了初始值.一般情况下初始值都是从 0 开始,然后按照一定的步长增加.在 MySQL 中只要定义了这个数的字节长度,那么就会 ...

  7. 使用 ref 和 out 传递数组注意事项

    1.与所有的 out参数一样,在使用数组类型的 out 参数前必须先为其赋值,即必须由被调用方为其赋值 示例 :在此例中,在调用方(Main 方法)中声明数组 theArray,并在 FillArra ...

  8. CentOS服务器安装Anaconda

    今天拿到了服务器,但是需要的环境都没有,从头开始配. 需要的环境很多,从装Anaconda开始. 版本相关:输入命令 cat /etc/redhat-release,我的版本是 CentOS Linu ...

  9. 剑指offer 打印从1到最大的n位数

    题目描述: 输入数字n,按顺序打印出从1到最大的n位十进制数.比如输入3,则打印出1.2.3一直到最大的3位数999. 分析:注意不能直接输入最大的n位十进制数,因为可能属于大数,这个数无法用int或 ...

  10. 关于使用iframe的父子页面进行简单的相互传值

    当一个页面使用了iframe作为嵌套时,如何想要将父页面的数据传给iframe子页面,那iframe所指向的呢个子页面是怎么获取呢,又或者子页面的数据要给父页面使用,那么父页面又如何获取子页面的数据呢 ...