提前准备好echarts.js官网下载地址:http://echarts.baidu.com/download.html
先定义一个data,用来存需要统计的数据(可以看做是请求返回的JSON数据):
var data = {
"month_start":"2017-11" ,
"month_end":"2018-04",
"resultlist":[{"time":"2017-11","sex_no":"-1","class_no":"1","times_sum":"3"},
{"time":"2017-11","sex_no":"0","class_no":"1","times_sum":"9"},
{"time":"2017-11","sex_no":"1","class_no":"1","times_sum":"7"},
{"time":"2017-11","sex_no":"-1","class_no":"2","times_sum":"5"},
{"time":"2017-11","sex_no":"2","class_no":"2","times_sum":"5"},
{"time":"2017-11","sex_no":"3","class_no":"2","times_sum":"2"},
{"time":"2017-11","sex_no":"4","class_no":"3","times_sum":"4"},
{"time":"2017-11","sex_no":"-1","class_no":"4","times_sum":"4"},
{"time":"2017-11","sex_no":"6","class_no":"4","times_sum":"4"},
{"time":"2017-11","sex_no":"7","class_no":"4","times_sum":"7"},
{"time":"2017-12","sex_no":"-1","class_no":"1","times_sum":"2"},
{"time":"2017-12","sex_no":"0","class_no":"1","times_sum":"24"},
{"time":"2017-12","sex_no":"1","class_no":"1","times_sum":"24"},
{"time":"2017-12","sex_no":"-1","class_no":"2","times_sum":"6"},
{"time":"2017-12","sex_no":"2","class_no":"2","times_sum":"5"},
{"time":"2017-12","sex_no":"3","class_no":"2","times_sum":"8"},
{"time":"2017-12","sex_no":"-1","class_no":"3","times_sum":"6"},
{"time":"2017-12","sex_no":"4","class_no":"3","times_sum":"5"},
{"time":"2017-12","sex_no":"5","class_no":"3","times_sum":"10"},
{"time":"2017-12","sex_no":"-1","class_no":"4","times_sum":"1"},
{"time":"2017-12","sex_no":"6","class_no":"4","times_sum":"7"},
{"time":"2017-12","sex_no":"7","class_no":"4","times_sum":"10"},
{"time":"2018-01","sex_no":"0","class_no":"1","times_sum":"25"},
{"time":"2018-01","sex_no":"1","class_no":"1","times_sum":"34"},
{"time":"2018-01","sex_no":"-1","class_no":"2","times_sum":"4"},
{"time":"2018-01","sex_no":"2","class_no":"2","times_sum":"12"},
{"time":"2018-01","sex_no":"3","class_no":"2","times_sum":"15"},
{"time":"2018-01","sex_no":"-1","class_no":"3","times_sum":"3"},
{"time":"2018-01","sex_no":"4","class_no":"3","times_sum":"4"},
{"time":"2018-01","sex_no":"5","class_no":"3","times_sum":"15"},
{"time":"2018-01","sex_no":"-1","class_no":"4","times_sum":"3"},
{"time":"2018-01","sex_no":"6","class_no":"4","times_sum":"20"},
{"time":"2018-01","sex_no":"7","class_no":"4","times_sum":"14"},
{"time":"2018-02","sex_no":"0","class_no":"1","times_sum":"8"},
{"time":"2018-02","sex_no":"1","class_no":"1","times_sum":"12"},
{"time":"2018-02","sex_no":"-1","class_no":"2","times_sum":"1"},
{"time":"2018-02","sex_no":"2","class_no":"2","times_sum":"2"},
{"time":"2018-02","sex_no":"3","class_no":"2","times_sum":"9"},
{"time":"2018-02","sex_no":"-1","class_no":"4","times_sum":"2"},
{"time":"2018-02","sex_no":"6","class_no":"4","times_sum":"12"},
{"time":"2018-02","sex_no":"7","class_no":"4","times_sum":"10"},
{"time":"2018-03","sex_no":"-1","class_no":"1","times_sum":"1"},
{"time":"2018-03","sex_no":"0","class_no":"1","times_sum":"2"},
{"time":"2018-03","sex_no":"1","class_no":"1","times_sum":"2"},
{"time":"2018-03","sex_no":"-1","class_no":"2","times_sum":"1"},
{"time":"2018-04","sex_no":"-1","class_no":"2","times_sum":"1"},
{"time":"2018-04","sex_no":"2","class_no":"3","times_sum":"20"},
{"time":"2018-04","sex_no":"1","class_no":"4","times_sum":"5"},
{"time":"2018-04","sex_no":"5","class_no":"1","times_sum":"7"}]
};
其中,time是月份,class_no是班级编号,times_sum是迟到次数,sex_no等于-1是冗余数据,其余的0、1代表一班男生、女生,2、3代表二班男生、女生,4、5代表三班男生、女生,6、7代表四班男生、女生(为什么要这样呢?后面会慢慢讲到)
最终实现效果:
先定义一个方法,根据传入开始月份和结束月份,返回一个月份数组(月份格式为:yyyy-mm):
/*根据始末月份获取该范围内所有月份*/
function getAllMonth(time_s,time_e) {
var startTime = new Date(time_s).getTime();// 转换为时间戳
var endTime = new Date(time_e).getTime();// 转换为时间戳
var arr = [];// 存放结果
var format = function(time) {// 最后的格式转换
var date = new Date(time);
return (date.getMonth() < 9)?(date.getFullYear() + '-0' + (date.getMonth() + 1)):(date.getFullYear() + '-' + (date.getMonth() + 1));//1-9?£???油0
};
var isLeapYear = function(year) {
return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);// 判断是否为闰年
};
// 月份映射 假设不为闰年
var MONTH = {
'1': 31,
'2': 28,
'3': 31,
'4': 30,
'5': 31,
'6': 30,
'7': 31,
'8': 31,
'9': 30,
'10': 31,
'11': 30,
'12': 31
};
arr.push(time_s);
if(time_s!=time_e){
while (startTime < endTime) {
var start = new Date(startTime);// 转换时间格式
if (isLeapYear(start.getFullYear()) && (start.getMonth() + 1 === 2)) {// 判断是否为闰年的2月份
startTime = startTime + 29 * 24 * 60 * 60 * 1000;
} else {
startTime = startTime + MONTH[start.getMonth() + 1] * 24 * 60 * 60 * 1000;
}
arr.push(format(startTime));
}
}
return arr;
}
获取月份范围数组,定义纵坐标:
var timeArr = getAllMonth(month_s,month_e);// 获取月份范围数组
var classNOArr = ['一班男生迟到次数','一班女生迟到次数','二班男生迟到次数','二班女生迟到次数',
'三班男生迟到次数','三班女生迟到次数','四班男生迟到次数','四班女生迟到次数'];//纵坐标
需要将data数据不同月份、不同班级存到一个二维数组中(目前的例子有6个月,4个班级(男、女又各一组)),结构如下图:
因此,上面提到的sex_no:0、1代表一班男生、女生,2、3代表二班男生、女生,4、5代表三班男生、女生,6、7代表四班男生、女生,正好对应二维数组的各行。所以,初始化为8X6的二维数组,初始元素全部为0。
//二维数组定义与初始化
var dataArr = new Array();
for(var i = 0; i < classNOArr.length; i++){
dataArr[i] = new Array();
for(var j = 0; j < timeArr.length; j++){
dataArr[i][j] = 0;
}
}
将sex_no作为二维数组的行下标,将原始的data数据分别存放的对应二维数组的位置,作为最终的绘图数据。
var list = (data.resultlist || []).sort(function(v1,v2){
return v1["time"] < v2["time"]?-1:1;//字符串比较,排序时间
});
//数据放入二维数组
for (var i = 0; i < list.length; i++) {
if(list[i]["sex_no"] != -1){
dataArr[list[i]["sex_no"]][timeArr.indexOf(list[i]["time"])] = list[i]["times_sum"];
}
}
定义series数据系列:
var seriesData = new Array();//series数据系列
for(var i = 0; i < timeArr.length;i++){
seriesData[i] = new Array();
}
将二维数组数据塞入series数据系列,并定义数据视图的表头、表格主体:
typeArr = classNOArr;
var length1 = 0;//循环遍历参数
var length2 = dataArr.length;//循环遍历参数
initData(length1,length2);
function initData(length1,length2){
for(var i = length1; i < length2;i++){
for(var j = 0; j < seriesData.length;j++){
seriesData[j].push(dataArr[i][j]);
}
}
table_header = ' ';
for(var i = length1; i < length2; i++){
table_header += ''+classNOArr[i]+' ';
}
for(var i = 0; i < timeArr.length; i++){
table_body += ''
+ ''
+ '' //数据视图彩色图例
+ timeArr[i]+' ';
for(var j = length1; j < length2; j++){
table_body +=''+dataArr[j][i]+' ';
}
table_body += ' ';
}
}
开始画图:
//series数据统一处理
function seriesArr(){
var serie = [];
for(var i = 0; i < timeArr.length; i++){
var item = {
name:timeArr[i],
type:'bar',
barMaxWidth : 50,
stack: '各班迟到次数统计',
data : seriesData[i],
itemStyle: {
normal:{
color:colorArr[i]
}
}
};
serie.push(item);
}
return serie;
}
var myChart = echarts.init(DOM.get('#main'));
option = {
tooltip : { //tooltip:气泡提示框,常用于展现更详细的数据
trigger: 'item', //或'axis'
axisPointer : { // 坐标轴指示器,坐标轴触发有效
type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend : {//legend:图例,表述数据和图形的关联
data:timeArr
},
toolbox : {
right : "10%",
show : true,
feature : {
mark : {
show : true
},
dataView : {
show : true,
readOnly : true,
optionToContent: function(opt) {
var series = opt.series;
var table = ''
+''
+ table_header
+ ' '
+ table_body
+ '
';
return table;
}
},
restore : {
show : false
},
saveAsImage : {
show : true
},
}
},
grid : { //grid:直角坐标系中除坐标轴外的绘图网格,用于定义直角系整体布局
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis : [//xAxis: 直角坐标系中的横轴,通常并默认为类目型
{
type : 'value', ////坐标轴类型,横轴默认为类目型'category',纵轴默认为数值型'value'
}
],
yAxis : [ //yAxis 直角坐标系中的纵轴,通常并默认为数值型
{
type : 'category', //坐标轴类型,横轴默认为类目型'category',纵轴默认为数值型'value'
data : typeArr,
name : '班级'
}
],
series : seriesArr() //数据系列
};
myChart.setOption(option);
//图例点击事件,全部取消选中时纵坐标显示为空。
myChart.on('legendselectchanged', function(obj) {
// console.log(option.yAxis[0].data);
var selected = obj.selected;
var option = myChart.getOption();
// myChart.clear();
for(var i = 0,j = 0;i < timeArr.length;i++){
if(selected[timeArr[i]] == false)
j += 1;
}
if(j == timeArr.length){
for(var i = 0;i < timeArr.length;i++){
selected[timeArr[i]] = true;
}
}
myChart.setOption(option,true);
});
}
完整代码:
echarts应用
代码还存在一些问题,后续添加一些简单功能并逐渐完善,比如说实现可选定只查某一个班级的数据等等。
希望我的分享能让学习相关知识的同学有所收获,欢迎大家批评指正,有什么好的方法和建议欢迎大家指教,万分感谢!