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 }
....=========啦啦啦啦~啦啦啦~( ̄▽ ̄~)(~ ̄▽ ̄)~=========....