关于echarts图表工具使用过程中的问题
这两天公司一款教育app上线,该app的后台资源上架的前端系统是我写的。因为上线之后领导要看一些像是下载页面访问,下载按钮点击,每日,每月的PV&UV数据,需要单独写一个子系统用来展示数据,业务逻辑倒是不复杂,后台的接口和数据都已经提供好了,我只需要请求接口,图表用echarts展示渲染数据到页面就可以了。
写的过程中遇到一些问题,在此记录一下。
我主要用的是折线图,其中X轴要显示日期,Y轴显示对应的的数据,每根折线是某款产品下各个渠道的数据。问题就出在产品下各个渠道的数据后台返回给我的日期不是连续性的,也就是会出现断层的现象。例如我查询的是2018-03-01到2018-03-07之间的数据,但是不同渠道下不是每天都有数据的,有的渠道只有03-01,03-02,有的是03-04,03-07,还有的渠道下什么数据也没有,而我X轴type的参数用的是'category'类目轴,本意是显示查询日期时间段内的连续日期,我问后台能不能如果该渠道下对应那天没有数据的,给我传0,后台的意思是这些数据都是数据库抓的,包括日期,如果当天没有数据的话,日期和数据都无法传给我。
没办法,只能根据他给我的数据自己处理一下了。本来是想补全查询日期时间段内的,后来想想只需要显示各个渠道下已有的日期就可以了,各个渠道下都没有的日期不展示在折线图上,如果渠道1有的日期渠道2没有,那自动给渠道2下当天的日期补充对应数据为0。
后台给我的数据格式是这样的(伪数据):
图一:
var datas={ "key1":[ { "time_string":"2018-03-01", "count":22 }, { "time_string":"2018-03-04", "count":24 } ], "key2":[ { "time_string":"2018-03-02", "count":88 }, ], "key3":[], "key4":[ { "time_string":"2018-03-03", "count":55 }, { "time_string":"2018-03-07", "count":996 }, ] }
而我最终的目的是获得我要的两个参数,一个是出现的日期以时间从远到近存在一个数组显示在坐标系的x轴上,另外一个参数是主要是为了要设置echarts折线图中series中每个渠道下的name和data字段;
最终要获得的数据应该是这样的(根据上面的data),存成数组或者对象都可以,我是存成了数组:
图二:
var handleData=[ ["2018-03-01","2018-03-02","2018-03-03","2018-03-04","2018-03-07"], [ { "name":"key1", "data":[22,0,0,24,0] }, { "name":"key2", "data":[0,88,0,0,0] }, { "name":"key4", "data":[0,0,55,0,996] }, ] ]
以上面的数据为例,我要查的是03-01到03-07日期的数据,而后台给我返回的数据格式是如图一这样的,其中日期只出现了1,2,3,4,7,日期的字段参数数组可以通过如下代码获得:
//根据时间字符串计算时间戳 function calcTimestamp(datestr) { var arr = datestr.split(" "); var date = arr[0];//日期 var arr0 = date.split("-"); var year = 2017, month = 0, day = 1; switch (arr0.length) { case 0: break; case 1: year = arr0[0]; break; case 2: year = arr0[0], month = arr0[1] - 1; break; case 3: year = arr0[0], month = arr0[1] - 1, day = arr0[2]; break; } return Date.parse(new Date(year, month, day)) / 1000;//秒 } //日期字符串 var timeString = []; for (var i = 0; i < datas.length; i++) { for (var key in datas[i]) { for (var k = 0; k < datas[i][key].length; k++) { if (timeString.indexOf(datas[i][key][k].time_string) == -1) { timeString.push(datas[i][key][k].time_string); } } } } console.log(timeString); //日期排序 for (var i = 0, l = timeString.length; i < l - 1; i++) { for (var k = i + 1; k < l; k++) { console.log(calcTimestamp(timeString[i])) if (calcTimestamp(timeString[i] + " 00:00:00") > calcTimestamp(timeString[k] + " 00:00:00")) { var tem = timeString[i]; timeString[i] = timeString[k]; timeString[k] = tem; } } } console.log(timeString);
日期参数有很多种灵活的方式获得,这里不做讨论。
第二个参数获得的代码如下:
var handleDataSeries = []; for (var m = 0; m < datas.length; m++) { var handleDataO = {}; for (var key in datas[m]) { handleDataO.name = key; handleDataO.lists = []; for (var z = 0; z < timeString.length; z++) { var flag = true; for (var n = 0; n < datas[m][key].length; n++) { if (timeString[z] == datas[m][key][n].time_string) { flag = false; handleDataO.lists.push(datas[m][key][n].count); break; } } if (flag) { handleDataO.lists.push(0); } } handleDataSeries.push(handleDataO); } }
这里的原理主要是用日期字符串来和数据中的time_string做比较,如果日期存在的,则把对应的count存储起来,如果不存在的,则存为0。
后记:如果要补全查询日期时间段内每个日期也是可以做到的,只是稍微麻烦一些,可以参考我写的《补全查询日期时间段内的日期》,用的是面向对象的方法写的。