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