(一)背景介绍
关于如何使用“eCharts”,这里我不做讲解,只概略讲一下,以后如何使用这一类工具的核心思想。
其实像“eCharts”这种开源构件,已经封装的很完善了,我们大多在本地使用的时候,配置项设置好之后,就可以正常使用了,而在配置项中,一些数据源是需要我们从和后台查询的,而这部分数据又是融合在配置项中的,如何将后台查询到的数据填充到配置项中,这才是关键。本文就以“eCharts”为例,说一说如何将后台查询到的数据填充到配置项中。
(二)案例
要想正常使用“eCharts”,我们必须配置好他的配置项,比如“eCharts”中的折线图堆叠中需要的配置项如下所示:
option = {
title: {
text: '折线图堆叠'
},
tooltip: {
trigger: 'axis'
},
legend: {
data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一','周二','周三','周四','周五','周六','周日']
},
yAxis: {
type: 'value'
},
series: [
{
name:'邮件营销',
type:'line',
stack: '总量',
data:[120, 132, 101, 134, 90, 230, 210]
},
{
name:'联盟广告',
type:'line',
stack: '总量',
data:[220, 182, 191, 234, 290, 330, 310]
}
]
};
而这里legend.data、xAxis.data、series.name和series.data是需要我们从后台查询数据来填充的。如何填充就是我们接下需要做的。
解决这个问题的关键就在于在JS文件中“eCharts”配置项后使用:
//深度拷贝
$.extend(true,option,response.option);
通过深度拷贝,将需要的数据填充进“option”,而拷贝的源,也就是上面的“response.option”就是我们需要通过Ajax请求,从后台获取的。
后台返回的数据格式必须保证和“option”配置项相同,这样才能保证进行深度拷贝。所以我们在后台需要做的就是构建Option对象,将后台需要返回的legend.data、xAxis.data、series.name和series.data全部放进“response.option”中,代码如下:
//“option”配置项之legend属性
public class Legend implements Serializable {
private List data;
public List getData() {
return data;
}
public void setData(List data) {
this.data = data;
}
}
//“option”配置项之xAxis属性
public class XAxis implements Serializable {
private List data;
public List getData() {
return data;
}
public void setData(List data) {
this.data = data;
}
}
//“option”配置项之series属性中的单个数据
public class Serie implements Serializable {
private String name;
private String type = "line";
private String stack;
private List data;
}
//“option”配置项
public class Option implements Serializable {
/**
* 1、这里面成员变量名都必须和echarts的option属性中的变量名保持一致,这样才能保证拷贝成功
* 2、各个成员变量对象包含哪些数据,根据echarts需要的数据需求,进行合理定制
* 比如:option属性中的xAxis变量,我们在js中已经规定好了type和boundaryGap,所以我们这里只需要提供data属性即可
*/
private Legend legend;
private XAxis xAxis;
private List series;
}
通过Option对象,就将这些数据全部整合成一个对象了。接下来我们去获取数据,然后构造Option对象,部分代码如下:
@Override
public Option constructOption(List<SalesStatistics> salesStatisticsList) {
/*
* Set:保证类别唯一(不会重复)
* TreeSet:保证每次取出来的顺序是一样的(HashSet每次取出来的顺序都可能不一样)
*/
Set<String> nameSet = new TreeSet<>();
/*
* 分析:因为同一类别不同时间段的数据需要组成一个集合,所以我们需要构建(“类别+时间”,数值)这样一个键值对,
* 这样我们在构建整个数据集的时候,就可以通过“类别+时间”来确定有没有值,没有的用“0”补上
*/
HashMap<String, String> datas = new HashMap<>();
for (SalesStatistics salesStatistics : salesStatisticsList){
String name = salesStatistics.getBusinessCategory();
String hour = salesStatistics.getHour();
Integer value = salesStatistics.getSalesNum();
//构建类别名数据集
nameSet.add(name);
//构建(“类别+时间”,数值)Map集
datas.put(name+hour, String.valueOf(value));
}
Option option = new Option();
Legend legend = new Legend();
XAxis xAxis = new XAxis();
List<Serie> series = new ArrayList<>();
//构造legend属性
List<String> nameList = new ArrayList<>();
nameList.addAll(nameSet);
legend.setData(nameList);
option.setLegend(legend);
//构造xAxis属性
List<String> hours = new ArrayList<>();
for (int i=0; i<=23; i++){
//格式化数据,不足两位,用0补齐
hours.add(String.format("%02d", i));
}
xAxis.setData(hours);
option.setxAxis(xAxis);
//构造series属性
//要求:同一个类别的组成一组数据,数据为空的,用0补齐
/*
* 问题:为什么先遍历name,再遍历hour?
* 原因:这样就保证name相同的数值,能够合并到一个Serie对象中
*/
for (String name : nameSet){
Serie serie = new Serie();
List<String> values = new ArrayList<>();
for (String hour : hours){
serie.setName(name);
serie.setStack("总量");
serie.setType("line");
values.add(datas.get(name + hour) == null ? "0" : datas.get(name + hour));
}
serie.setData(values);
series.add(serie);
}
option.setSeries(series);
return option;
}