如何實現echarts組織結構圖節點的收縮


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一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM