Echarts折線圖表斷點如何補全

funnyZpC發表於2017-07-08

                                                             Echarts折線圖如何補全斷點以及如何隱藏斷點的title

  做報表的時候,尤其是做圖表的時候時常會碰到某一記錄的值中缺少某個時間段(比如月份或季度)的值,導致圖表顯示殘缺不全,for example:

        

如果照實顯示的話確實不太美觀(除非貴公司確實需要特別準確的資料除外~),當然我們的客戶是做信託的,算錢的系統和時常開會追KPI的時候看報表系統~;給領導寫報告圖表當然不能太另類~\(≧▽≦)/~,遂業務部門的同學要求我們儘可能在資料準確的情況下將圖表做的更美觀些些,...吾以為這個貌似難難滴欸。。。。,怎麼辦。。。。,研究來研究去,之後我們將報表做成了這樣紙>>> 

        

    感覺挺好的,不知業務的妹紙是否滿意(✿◡‿◡)

 且細看....細看,比如圖中34個月與35個月是沒有資料滴,哈哈,成功!!

一下分享下我的思路:

        A>首先要取得所有部門的期限內的所有資料(當然這個過程你需要自己碼程式碼獲得一份完整的月份資料,要不然你怎麼知道記錄的斷點位置呢,是不?)

        B>然~,整理你的資料,分層是必要的(如果資料庫能按按部門分層月份,幹嘛還要這麼累啊(=@__@=))

        C>再~,兩層遍歷,等等幹什麼呢?-->這是要找出斷點,並用統一的mark以標示

          (具體就是外層迴圈月份List,然後遍歷所有的按部門歸類的部門的月份找出此部門再哪個期限缺值)

        D>然~,看似以上已經找出了斷點了,但試想下如果這些斷點都是以‘—’補全,圖還是會斷啊~~~,怎麼辦;

           啊哈 so easy~ 將此斷點補上前後兩個值的平均值不就是一條直線啦,啦啦啦~

        E>啦啦啦,搞定\(^o^)/YES!   。。。。,瀏覽器開啟頁面~ (⊙﹏⊙)b 為什麼為什麼為什麼還會顯示title呢,

           這樣會暴露程式猿的審美····,how? 官方API搞定....

 直接放程式碼可能讓各位一頭霧水,先給一份樣例資料方便大家除錯:

          

下圖是具體程式碼:

   注:echarts需要的資料樣例如19~31註釋部分

      37~40行獲取limits資料,也就是x軸月份資料

      30~56行處理echarts分層資料(按部門劃分)

      62~121行處理斷點資料(將已經分層的裡面的月份‘—’處理成前後值的平均數,使折線平滑)

          在這個之前需要對月份資料排序(從小到大排序),方法在最下面哈

      至於怎麼將斷點資料預設不顯示,呢,答案很簡單->請注意104行裡面有個引數:“symbol:'none'”,這是官方API

        如對最後的圖表的結構資料不懂,請看這裡,看這裡:http://echarts.baidu.com/echarts2/doc/example/line2.html

 

  1     function generateChart04() {
  2         var detailData = module.page["allFundStatD4s"].detaillist,
  3                legendData=[],//標題名稱組
  4                limits=[],//期限
  5                myData={},//系列資料
  6                label={normal:{
  7                          show: true,
  8                          //position: 'top',
  9                          formatter: '{c}%'
 10                      }},
 11                seriesData=[];
 12         /**
 13          * A>構建系列結構資料
 14          * B>系列資料格式化和斷點處理
 15          * C>圖表顯示樣式處理
 16          */
 17         /*
 18          * 系列資料樣例->
 19          * {"廣州管理部":{
 20          *                             "期限":{1:0.173,6:0.863,9:0.777,12:0.66,36:0.039},#myLimits
 21          *                             "datas"{"廣州管理部",type:"line",data:"(取)期限",
 22          *                                     label:{
 23          *                                              normal: {
 24                                                      show: true,
 25                                                      position: 'top',
 26                                                      formatter: '{c}%'
 27                                                  },
 28          *                                     }
 29          *                                     }
 30          *                         }
 31          * }
 32          */
 33         for(var i in detailData){
 34             //如果沒有當前legend值,先初始化新建個;如果有,則更新當前期限值
 35             if(!myData[detailData[i].deptName]){
 36                 legendData.push(detailData[i].deptName);//放入圖表標題陣列中
 37                 if(limits.indexOf(detailData[i].realTimeLimit)==-1){//不存在
 38                 //if(!(limits.includes(detailData[i].realTimeLimit))){
 39                     limits.push(detailData[i].realTimeLimit);//放入期限陣列中
 40                 }
 41                 myData[detailData[i].deptName]={};//宣告
 42                 myData[detailData[i].deptName].myLimits={};//宣告
 43                 myData[detailData[i].deptName].myLimits[detailData[i].realTimeLimit]=detailData[i].compositeCost;//放入期限
 44                 myData[detailData[i].deptName].datas={};
 45                 myData[detailData[i].deptName].datas.name=detailData[i].deptName;//當前legend放入名稱
 46                 myData[detailData[i].deptName].datas.type="line";//當前legend放入型別
 47                 myData[detailData[i].deptName].datas.data=[];//先預留,取到所有系列資料後再填入資料
 48                 myData[detailData[i].deptName].datas.label=label;//線型預設值
 49             }else{
 50                 if(limits.indexOf(detailData[i].realTimeLimit)==-1){//不存在
 51                 //if(!(limits.includes(detailData[i].realTimeLimit))){
 52                     limits.push(detailData[i].realTimeLimit);//放入期限陣列中
 53                 }
 54                 myData[detailData[i].deptName].myLimits[detailData[i].realTimeLimit]=detailData[i].compositeCost;//放入期限
 55             }
 56         }
 57         limits.sort();//從小到大排序
 58         /**
 59          * 遍歷各個legend
 60          * 填補當前legend的節點資料為‘-’(以便後續對此節點補充平均值以使折線不出現明顯的斷點)
 61          */
 62         for(var j in myData){
 63             for(var k in limits){
 64                 if(myData[j].myLimits[limits[k]]){
 65                     myData[j].datas.data.push((myData[j].myLimits[limits[k]]*100).toFixed(2));
 66                     //myData[j].datas.data.push(myData[j].myLimits[limits[k]]==-1?0:(myData[j].myLimits[limits[k]]*100).toFixed(2));
 67                 }else{
 68                     myData[j].datas.data.push("-");
 69                 }
 70             }
 71 
 72             /**
 73              * 中間斷點的補全中間斷點
 74              */
 75             //[-,-,0,99,-,5,-,-];
 76             var before=0,after=0,cnode=0,idx=0;
 77             for(var m in myData[j].datas.data){
 78                 idx=idx+1;
 79                 if(myData[j].datas.data[m]=="-"){
 80                     //continue;//返回,進行下一次迴圈
 81                     if(m==0){
 82                         continue;
 83                     }else{
 84                         if(before>0){
 85                             cnode=cnode+1;
 86                             after=idx-1;
 87                         }
 88                     }
 89                     if(myData[j].datas.data[m]==(myData[j].datas.data.length-1)){
 90                         //初始化標記值
 91                         before=0;
 92                         after=0;
 93                         cnode=0;
 94                     }
 95                 }else{
 96                     if(cnode==0){
 97                         before=idx-1;//當前資料的下標的位置
 98                         after=idx-1;//當前資料下標的位置
 99                     }else{
100                         after=idx-1;
101                         cnode=cnode+1;
102                         for(var n=1;n<cnode;n++){
103                             //myData[j].datas.data[before+n]=(Number(myData[j].datas.data[before])+(myData[j].datas.data[after]-myData[j].datas.data[before])/cnode*n).toFixed(2);
104                             myData[j].datas.data[before+n]={name:limits[before+n]+ "個月", symbol:'none', value:(Number(myData[j].datas.data[before])+(myData[j].datas.data[after]-myData[j].datas.data[before])/cnode*n).toFixed(2)};
105                         }
106                         cnode=0;
107                         before=idx-1;
108                     }
109                     if(!(myData[j].datas.data[Number(m)+1])){//下一個節點是否存在
110                         //存在"-":continue;
111                         //存在number:
112                         
113                         //初始化標記值
114                         before=0;
115                         after=0;
116                         cnode=0;
117                     }
118                 }
119             }
120             seriesData.push(myData[j].datas);
121         }
122         
123         //X軸資料新增字尾
124         for(var l in limits){
125             limits[l]=limits[l]+"個月";
126         }
127         var myChart = echarts.init(document.getElementById('chart4'),'macarons');
128         option = {
129             title : {
130                 text: '按部門期限分佈',
131                 x:'center',
132                 y:'20px',
133                 position:'top'
134             },
135             grid:{ 
136                 y:'80px',            //直角座標系內繪圖網格左上角縱座標,預設值60
137                 x:'150px',
138                 x2:'1%',
139                 y2:'9%'
140             },
141             tooltip : {
142                 trigger: 'axis',
143                 formatter:function(params)
144                 {
145                     var relVal;
146                     if (Array.isArray(params)) {    //顯示各項資料時,params為陣列
147                         relVal = params[0].name;
148                         for (var i = 0, l = params.length; i < l; i++) {
149                             relVal += '<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + params[i].color + '"></span>'
150                             relVal +=  params[i].seriesName + ' : ' + params[i].value+"%";
151                         }
152                     } else {    //顯示平均數時,params為物件
153                         relVal = params.name;
154                         relVal += '<br/>' + params.seriesName + ' : ' + params.value+"%";
155                     }
156                     return relVal;
157                 }
158             
159             },
160             legend: {
161                 data: legendData,//['資金成本','指導價'],
162                 y:"center",//y:'20px;',
163                 x:"left",
164                 orient:"vertical"
165             },
166             toolbox: {
167                 show : true,
168                // orient:"vertical",
169                 feature: {
170                     dataView : {show: true, readOnly: false},
171                     magicType : {show: true, type: ['line', 'bar']},
172                     restore : {show: true},
173                     saveAsImage : {show: true, backgroundColor:'transparent'}
174                 }        
175             },
176             xAxis:{
177                 /* type: 'category', */
178                 position:'right',
179                 data: limits,
180                 boundaryGap: true,
181                 axisLabel:{
182                     interval:0,
183                     rotate:45,//傾斜度 -90 至 90 預設為0
184                 },
185             },
186             yAxis: {
187                 type: 'value',
188                 boundaryGap: [0.3, 0.3],
189                 scale: true,
190                 axisLabel: {
191                     //formatter: '{value}%'
192                     formatter: function (value, index) {
193                         if(value.toString().length>5){
194                               return Number(value.toFixed(5))+"%";    
195                         }else{
196                             return value+"%";
197                         }
198                               
199                      }
200                 }
201             },            
202             series :seriesData,
203         };
204         myChart.setOption(option);
205     }

 

1     //陣列按按數字從小到大排序
2     function (val, nextVal) {
3             return val-nextVal;
4     }

 

        ....=========啦啦啦啦~啦啦啦~( ̄▽ ̄~)(~ ̄▽ ̄)~=========....

 

相關文章