在 SpringBoot+MyBatisPlus+Redis+Thymeleaf+Echarts 实现学生成绩管理系统中我们 实现了可视化柱状图和扇形图,本文基于该项目总结一个项目中通用的、实现类似的可视化实践,希望对初步使用Echarts有一些帮助。
1.准备统计信息实体类
它可以用来接收查询结果,也就是Mybatis
的resultMap封装类型。
/**
* 统计
* @author Huishi
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Statistics {
private String className;
private Double maxScore;
private Double minScore;
private Double avgScore;
private Integer countStudent;// 学生人数
}
2.将统计信息List集合变为MapList集合
原来的List集合中是不同班级的统计信息对象,例如
第一个对象:属性是1班,最高分xxx,最低分xxx
第二个对象:属性是2班,最高分xxx,最低分xxx......
但是Echarts比如要显示分数柱状图,那么就是
*最高分*:[1班的最高分, 2班的最高分, ......]
*最低分*:[1班的最低分, 2班的最低分, ......]
所以我们可以把它变成类似的结构,那么最高分就是一个Map的key,value就是每个对象的最高分属性构成的List集合。这样在前端直接get方法就可以获取对应的值了。
如何确保一定是按班级顺序排列的?
只要你在数据访问层的SQL语句中order by class_name
,返回的类型是List<Statistics>
就是有序的,那么对集合中的对象依次变为map并获取对应的key这一顺序,也是有序的。
/**
* Pojo -> Map<String, Object>
* @param obj
* @return
* @throws Exception
*/
public static Map<String,Object> object2Map(Object obj) throws Exception{
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = obj.getClass().getDeclaredFields();
for(Field field:fields){
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
}
/**
* List<T> --> Map<String, List<Object>>
* @param objectList
* @param keyName
* @param <T>
* @return
* @throws Exception
*/
public static <T> Map<String, List<Object>> objectList2MapList(List<T> objectList, String[] keyName) throws Exception{
Map<String, List<Object>> resultMap = new HashMap<>();
for(int i = 0; i < keyName.length; i++){
List<Object> arrayList = new ArrayList<>();
for (T t: objectList){
// List有序,所以对每个对象依次变为map,然后得到对应的值,存入arrayList
arrayList.add(object2Map(t).get(keyName[i]));
}
resultMap.put(keyName[i], arrayList);//将keyName和对应List集合存入resultMap
}
return resultMap;
}
3.在控制层加入模型并返回视图
从Service层获得统计信息List集合,调用之前的方法,加入模型,返回视图。这里没有用前后端分离,有兴趣的小伙伴可以试一下。
/**
* 统计学生信息
*/
@RequestMapping("/stat.action")
public String stat(Model model) throws Exception {
List<Statistics> statistics = studentService.statistics();
// 用于柱状图、扇形图
Map<String, List<Object>> resultMap = BeanUtil.objectList2MapList(statistics, new String[]{
"minScore", "maxScore", "avgScore", "countStudent", "className"});
model.addAttribute("stat", statistics);
model.addAttribute("statMap", resultMap);
return "menu/stat";
}
4.柱状图实现
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main_vis" style="width: 600px;height:400px;"></div>
<div id="main_vis2" style="width: 600px;height:400px;"></div>
<script type="text/javascript" th:incline="javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main_vis'));
var option = {
title: {
text: '学生成绩柱状图'
},
tooltip : {
},
legend: {
data: ['平均分','最高分','最低分']
},
xAxis: {
// data: ['衬衫','羊毛衫','雪纺衫','裤子','高跟鞋','袜子']
data: [[${
statMap.get("className")}]],
name: '班级'
},
yAxis: {
name: '分数'
},
series: [{
name: '平均分',
type: 'bar',
data: [[${
statMap.get("avgScore")}]]
},{
name: '最高分',
type: 'bar',
data: [[${
statMap.get("maxScore")}]]
},{
name: '最低分',
type: 'bar',
data: [[${
statMap.get("minScore")}]]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
5.扇形图实现
可以通过遍历数组的方式建立data的对象数组。
/*-----------------------------------------------------------*/
//显示扇形图表2
var mychart2 = echarts.init(document.getElementById('main_vis2'),'light');
// 得到List
var countStudent = [[${
statMap.get("countStudent")}]];
var className = [[${
statMap.get("className")}]];
var serie = [];
for (let i = 0; i < className.length; i++){
serie[i] = {
}; // JS数组中包含多个对象
serie[i].value = countStudent[i];
serie[i].name = className[i] + '班';
}
// alert("长度"+countStudent.length+countStudent)
var option2 = {
title: {
text: '学生人数占比'
},
tooltip : {
trigger: 'item',
formatter: "{b} : {c} 人({d}%)"//设置显示内容
},
series: [{
type: 'pie',
data: serie
// data: [
// // {value:1, name:'视频广告'},
// // {value:2, name:'联盟广告'}
// ]
}],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
normal:{
label:{
show: true,
formatter: '{b} : {c} ({d}%)'
},
labelLine :{
show:true}
}
}
};
// 使用刚指定的配置项和数据显示图表。
mychart2.setOption(option2);
</script>
完整的代码可以在我的github中查看