上一篇文章 新手学HighCharts(一)—-基本使用 中介绍了highCharts的基本使用,今天给大家介绍对比柱状图的使用,贴张图先:
在highcharts中有一个属性series
,这个属性主要是配置图表要展示的数据。
var series = [
{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2,
26.5, 23.3, 18.3, 13.9, 9.6]
},
{
name: 'New York',
data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8,
24.1, 20.1, 14.1, 8.6, 2.5]
},
{
name: 'Berlin',
data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6,
17.9, 14.3, 9.0, 3.9, 1.0]
},
{
name: 'London',
data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0,
16.6, 14.2, 10.3, 6.6, 4.8]
}
];
每一个系列是个数组,每一项在图片中都会生成图表中一个图标分类的数据,如上面的柱状图,每一个系列都是一个不同颜色的柱状。
那么如何动态加载这些数据呢?刚才在上面说了,series
中每一个系列都是一个数组,每一个系列的加载形式是这样的,举个栗子:
[Array[2],Array[2],Array[2],Array[2]]
这个就是一个简单的柱状图:
再往里面细分一下是这样的
[[“平均值”,70],[“最高分”,99],[“最低分”,35],[“及格率”,80]]
展示下B层实现类里面具体的实现方法:
/** * 根据班级ID和课程ID查询图表数据(集合) * @param check_class 班级ID数组 * @param courseId 课程ID * @param exam_DataBase 数据库名称 * @return */
public List<List<Map<Serializable, Serializable>>> queryChartByCouAndClaList(String check_class, String courseId,String passMark, String dataBaseName)
{
StudentScoreBean studentScoreBean;
List<StudentScore> studentScore=null;
String[] class_check;
ScoreAnalyzeByClassView classScore=new ScoreAnalyzeByClassView();
List<List<Map<Serializable,Serializable>>> listReturnMap=new ArrayList<List<Map<Serializable,Serializable>>>();
try {
//远程调用链接
studentScoreBean=(StudentScoreBean)this.lookupRemoteBean(studentScoreURL);
class_check = check_class.split(",");
//循环遍历数组,获取classId
for(int i=0;i<class_check.length;i++)
{
//调用查询方法
String classId=class_check[i].toString();
studentScore=studentScoreBean.queryScoreByCourseAndClass(courseId, classId, dataBaseName);
//数据分析统计
int max=Integer.parseInt(studentScore.get(0).getTotalScore());
int min=Integer.parseInt(studentScore.get(0).getTotalScore());
int sum=0;
int pass=0;
//最低分、最高分
//循环遍历获取最高分和最低分
for(int j=0;j<studentScore.size();j++)
{
int value=Integer.parseInt(studentScore.get(j).getTotalScore());
//最大值和最小值
if(min>value)
{
min=value; //最大值
}
if(max<value)
{
max=value; //最小值
}
//总和
int num=value;
sum+=num;
//及格人数
if(value>=Integer.parseInt(passMark))
{
pass+=1;
}
}
//求平均值
double avg=sum/studentScore.size();
//及格率
double passMK=pass*100/studentScore.size();
classScore.setClassAvgScore(String.valueOf(avg));
classScore.setClassHighScore(String.valueOf(max));
classScore.setClassLowScore(String.valueOf(min));
classScore.setClassPassRate(String.valueOf(passMK));
Map<Serializable,Serializable> map1=new HashMap<Serializable,Serializable>();
map1.put("name", "平均分");
map1.put("count", Double.parseDouble(classScore.getClassAvgScore()));
Map<Serializable,Serializable> map2=new HashMap<Serializable,Serializable>();
map2.put("name", "最高分");
map2.put("count", Double.parseDouble(classScore.getClassHighScore()));
Map<Serializable,Serializable> map3=new HashMap<Serializable,Serializable>();
map3.put("name", "最低分");
map3.put("count", Double.parseDouble(classScore.getClassLowScore()));
Map<Serializable,Serializable> map4=new HashMap<Serializable,Serializable>();
map4.put("name", "及格率");
map4.put("count", Double.parseDouble(classScore.getClassPassRate()));
List<Map<Serializable,Serializable>> listMap=new ArrayList<Map<Serializable,Serializable>>();
listMap.add(map1);
listMap.add(map2);
listMap.add(map3);
listMap.add(map4);
listReturnMap.add(listMap); //在list集合外在嵌套一层list
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return listReturnMap;
}
因为界面显示时用到的不只是一条数据,所以返回值在list外面有嵌套了一层list,每一个List<Map<Serializable,Serializable>>
在经过json转换之后,都是一个系列,在嵌套一层list,就是多个系列。
Controller层没什么好说的,只是起到一个接受界面数据,传给B层;接受B层处理的数据,返给界面;主要的业务逻辑处理都在B层。
/** * 根据班级ID和课程ID查询图表数据(集合) * @param request * @param response */
@RequestMapping("/queryChartByCouAndClaList")
public void queryChartByCouAndClaList(HttpServletRequest request,HttpServletResponse response)
{
//获取前台界面数据
String check_class=request.getParameter("Check_val");
String courseId=request.getParameter("CourseId");
String passMark=request.getParameter("PassMark");
//查询数据
List<List<Map<Serializable, Serializable>>> listChart=scoreAnalyzeFacadeClassBean.queryChartByCouAndClaList(check_class,courseId,passMark,Exam_DataBase);
//json转换
jacksonJsonUntil.beanToJson(response, listChart);
}
图表显示,jsp中只需要给highcharts定义一个容器存放就行。
<div id="columnChart" style="width:900px; height: 500px; margin-top:20px;"></div>
在实现动态加载的过程中,重要的地方一个是B层的业务逻辑实现,另一个就是javascript中的一个转换。
当后台数据经过json转换之后,传达js里面的数据形式是这样的:
[Array[4],Array[4]]
这样的话还不能够显示,为什么,因为每个Array下,存的是一个个的对象,给highcharts的数据显示不一样,每一个Array下的具体形式是这样的:
[Object[2],Object[2],Object[2],Object[2]]
每一个Object下再分才是具体的数据
[“平均值”,70]
所以还需要把接受到的数据进行转换,转换成适合highcharts显示的格式:
var title="班级成绩对比分析";
var renderToDiv="columnChart"; //要加载到的div
GetOptions(renderToDiv,title); //获取highcharts的基本样式
options.series=new Array();
var i,j;
for(i=0;i<check_val.length;i++) //循环赋值
{
options.series[i]=new Object(); //实例化对象
options.series[i].name=class_name[i]; //获取班级名称
var array=[]; //定义数组
for(j=0;j<data[i].length;j++) //循环获取柱状图数据
{
var result=new Array(data[i][j].name,data[i][j].count);
array.push(result);
}
options.series[i].data=array;
}
如果你细看的话,就会发现一个问题,其中的GetOptions
是哪来的,不要着急,下面给你介绍,Highcharts库使用的是json格式来配置的数据,首先定义highcharts的基本样式
var chart;
var options;
function GetOptions(renderToDiv,title) {
options={
chart: {
type: 'column',
renderTo: renderToDiv, //添加到那个div下
},
credits: {
enabled: false,
},
title: {
text: title
},
xAxis: {
categories: [
],
labels: {
rotation: 0,
align: 'right',
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: '总值'
}
},
legend: {
enabled: true //图例开关
},
tooltip: {
//pointFormat: '总值',
},
series: [{
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
x: 4,
y: 10,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif',
textShadow: '0 0 3px black'
}
}
}]
}
}
这些都是一些可以复用的属性,然后再把数据动态的加载到options中,把整个样式放到准备好的盛放容器中就可以了。
chart=new Highcharts.Chart(options); //实例化一个新的Highcharts图表
这样,图表就成功的动态加载出来了!