(1)先看一眼整体流程图
(2)我觉得最重要的部分就是数据的处理部分,当然数据的获取我没在上图画出来,下面给出我的servlet(框架ssm)
@RequestMapping(value="/systemHistory",method=RequestMethod.POST)
public void systemHistoryPOST(@RequestParam String dateStart,
@RequestParam String dateEnd, @RequestParam Integer modelId,
HttpServletRequest request ,HttpServletResponse response) throws Exception{
//根据modelId查询相应的信息。。。
Map<String,Object> paraMap =factoryService.getParametersByModelId(modelId);
String tableName =(String)paraMap.get("para_url");
System.out.println("tableName="+tableName);
log.info("******************************************************");
Map<String, Object> dateMap = DateFilter.dateFilter(dateStart, dateEnd);//DateFilter是工具类,作用是把合格的String日期转换为Date类型后存入map
dateMap.put("tableName",tableName);//dateMap的可以有:dStart,dEnd,tableName
List<Object> hisDataList = factoryService.getHistoryDataByDate(dateMap);//读取数据库datetime类型的日期会变成java.sql.Timestamp
log.info("******************************************************");
JSONObject jsonObject = new JSONObject();
jsonObject.put("paraMap",paraMap);
JSONArray.fromObject(hisDataList);//将List<Object>转化为json数组
jsonObject.put("hisDataList",hisDataList);
log.info("服务器返回的json数据:"+jsonObject.toString());
PrintWriter out = null;
try {
out = response.getWriter();
out.println(jsonObject.toString());
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
图解我的数据结构:
(3)ajax成功后返回result数据:
$.ajax({
url:"${pageContext.request.contextPath}/systemHistory.html?modelId="+modelId+"&dateStart="+dateStart+"&dateEnd="+dateEnd,
type:"post",
dataType : 'json',
contentType:'application/json; charset=utf-8',
success:function(result){XXXX}
})
(4)动态创建数组arr0,arr1.arr2..,其中arr0用来存放所有的参数名,arr1用来存time,剩下的就存储参数对应的历史数据。
//(1)初始化
var paraMap = result.paraMap;
var paraNum = paraMap.para_num;//获取当前系统的字段个数,有几个就创建(几+2)个数组
console.log('paraNum='+paraNum);
var historyData = result.hisDataList;
for(var i=0;i<=paraNum+1;i++){//动态创建变量名.arr0,arr1.arr2..,其中arr0用来存放所有的参数名,arr1用来存time
var varName = 'arr'+i;
window[varName]=[];
}
(5)将历史数据存入对应数组
//(2)获取所有参数名,存arr0
var n=1;
for(var k in paraMap){
if(k != 'image_name'){
var regExp = new RegExp("name");
if(regExp.test(k)){
var paraName = paraMap[k]; //取出某系统的参数对应的数据,存入对应数组
arr0.push(paraName);
n++;
}
}
}
for(var i=0;i<arr0.length;i++){//测试,输出arr0
console.log('arr0:'+arr0[i]);
}
//(3)获取对应参数的历史数据,存入对应数组
var hisDataNum = historyData.length;
console.log('hisDataNum='+hisDataNum);
var varTime = 'arr'+1;
for (var j = 0; j < hisDataNum; j++) {
var time = historyData[j]['time'];
window[varTime].push(timeStamp2String(time.time)); //将时间timestamp转Date再加到数组arr1里,因为数组是有序的,所以倒序后,第一个map的时间在最前面,依次索引+1
}
for (var i = 0; i < paraNum; i++) {//动态添加数据到相应数组
var varName = 'arr'+(i+2);
for (var j = 0; j < hisDataNum; j++) {
window[varName].push(historyData[j][arr0[i]]);
}
}
注意这里的时间格式,我使用函数timeStamp2String(),把timestamp转为datetime。
function timeStamp2String (time){//js timestamp转datetime
var datetime = new Date();
datetime.setTime(time);
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1;
var date = datetime.getDate();
var hour = datetime.getHours();
var minute = datetime.getMinutes();
var second = datetime.getSeconds();
// var mseconds = datetime.getMilliseconds();
return year + "-" + month + "-" + date+" "+hour+":"+minute+":"+second;
};
(6)画直线图
6.1)先看一下HighCharts格式 或者说 创建模式:对象-属性-对象
6.2)push方式,注入相应的数据给HighCharts的属性。
for(var i=0;i<arr1.length;i++){//将时间push到categories数组中,
charts.xAxis.categories.push(arr1[i]);
}
先自己拼接一个新对象,然后在push到给你的目的属性
var m;
for(m = 0;m<paraNum;m++){//0,1,2,3,多级Y轴---将yAxisObj对象push到charts.yAxis数组中,
var yAxisObj={"labels":{"format":'°C',"style":{"color":"Highcharts.getOptions().colors["+m+"]"}},"title":{"text":arr0[m],"style":{"color":"Highcharts.getOptions().colors["+m+"]"}},"opposite":false} ;
if(m%2!=0){
yAxisObj.opposite=true;
}
charts.yAxis.push(yAxisObj);
var dataArray = "arr"+(m+2);
console.log("dataArray="+dataArray);
var seriesObj={"name":arr0[m],"type":"spline","yAxis":m,"data":eval(dataArray),"tooltip":{"valueSuffix":"°C"},"visible":false};
if(m==0){
seriesObj.visible=true;
}
charts.series.push(seriesObj);
}
6.3)实例化HighCharts,并注入之前创建号的charts对象
var options=new Highcharts.Chart(charts);
6.4)贴出效果图
(7)最后给出完整的jsp代码,以供参考
<%@ page import="java.lang.String"%>
<%@ page import="java.lang.Integer"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/main.css"/>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/datePicker/WdatePicker.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/lhgdialog/lhgdialog.min.js?t=self&s=areo_blue"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/highstock.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/exporting.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/export-csv.js"></script>
</head>
<body >
<div class="search_div">
日期区间:
<input type="text" id="dateStart" name="dateStart" onclick="display()" readonly="readonly" style="width:140px;"/> -
<input type="text" id="dateEnd" name="dateEnd" onclick="display()" readonly="readonly" style="width:140px;"/>
<a href="javascript:search();" class="myBtn"><em>开始查询</em></a>
</div>
<div id="container" style="min-width:800px;height:400px"></div>
<script type="text/javascript">
/*
点击日期控件按钮,选择日期
*/
function display(){
WdatePicker({skin:'whyGreen',startDate:'%y-%M-%d %H:00:00',dateFmt:'yyyy-MM-dd HH:mm:ss'});
}
/*
点击‘开始查询’,执行此方法,获取控件的开始,结束时间
*/
function search(){
var dateStart = document.getElementById("dateStart").value;
var dateEnd = document.getElementById("dateEnd").value;
console.log('dateStart='+dateStart+',dateEnd='+dateEnd);
if(dateEnd==""||dateStart <= dateEnd){//输入正常,将输入的开始,结束时间传给服务器
/* 下面开始全自动化读取数据什么的了 */
var modelId = ${modelId};
printCharts(modelId,dateStart,dateEnd);//什么都不说了,千言万语都在这个方法里了!
}else{
alert("开始时间不能大于结束时间!");
}
}
/*
使用Highcharts,绘制表格
*/
function printCharts(modelId,dateStart,dateEnd){
console.log('正在发送ajax请求');
$.ajax({
url:"${pageContext.request.contextPath}/systemHistory.html?modelId="+modelId+"&dateStart="+dateStart+"&dateEnd="+dateEnd,
type:"post",
dataType : 'json',
contentType:'application/json; charset=utf-8',
success:function(result){
//(1)初始化
var paraMap = result.paraMap;
var paraNum = paraMap.para_num;//获取当前系统的字段个数,有几个就创建(几+2)个数组
console.log('paraNum='+paraNum);
var historyData = result.hisDataList;
/* for(var i=0;i<historyData.length;i++){//从list获取数据
console.log(historyData[i]);
} */
for(var i=0;i<=paraNum+1;i++){//动态创建变量名.arr0,arr1.arr2..,其中arr0用来存放所有的参数名,arr1用来存time
var varName = 'arr'+i;
window[varName]=[];
//console.log('arr'+i);
}
//(2)获取所有参数名,存arr0
var n=1;
for(var k in paraMap){
if(k != 'image_name'){
var regExp = new RegExp("name");
if(regExp.test(k)){
var paraName = paraMap[k]; //取出某系统的参数对应的数据,存入对应数组
arr0.push(paraName);
n++;
}
}
}
for(var i=0;i<arr0.length;i++){//测试,输出arr0
console.log('arr0:'+arr0[i]);
}
//(3)获取对应参数的历史数据,存入对应数组
var hisDataNum = historyData.length;
console.log('hisDataNum='+hisDataNum);
var varTime = 'arr'+1;
for (var j = 0; j < hisDataNum; j++) {
var time = historyData[j]['time'];
window[varTime].push(timeStamp2String(time.time)); //将时间timestamp转Date再加到数组arr1里,因为数组是有序的,所以倒序后,第一个map的时间在最前面,依次索引+1
}
for (var i = 0; i < paraNum; i++) {//动态添加数据到相应数组
var varName = 'arr'+(i+2);
for (var j = 0; j < hisDataNum; j++) {
window[varName].push(historyData[j][arr0[i]]);
}
}
//开始画表格了
/*
生成4个数组,arr1,arr2,arr3,arr4
arr1存放第1个参数的数据
arr2存放第2个参数的数据
arr3存放第3个参数的数据
arr4存放第4个参数的数据
*/
/* console.log('arr0存参数:'+arr0);
console.log('arr1存时间:'+arr1);
console.log('arr2存参数'+arr0[0]+':'+arr2);
console.log('arr3存参数'+arr0[1]+':'+arr3);
console.log('arr4存参数'+arr0[2]+':'+arr4);
console.log('arr5存参数'+arr0[3]+':'+arr5); */
var charts ={// 图表初始化函数,其中 container 为图表的容器 div
chart: {
renderTo: 'container',
zoomType: 'xy'
},
title: {
text: '生产数据'
},
xAxis:{
title: {text: '时间'},
categories:[],
crosshair: true,
//tickInterval:2
},
yAxis:[], //动态生成多级y轴
tooltip: {
shared: true
},
legend: {
layout: 'vertical',
align: 'left',
x: 150,
verticalAlign: 'top',
y: 5,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
},
series:[]
};
/* console.log('charts.xAxis='+charts.xAxis);
console.log('charts.xAxis.title='+charts.xAxis.title);
console.log('charts.xAxis.title.text='+charts.xAxis.title.text);
console.log('charts.xAxis.categories='+charts.xAxis.categories);
console.log('charts.yAxis='+charts.yAxis);
console.log('charts.series='+charts.series); */
for(var i=0;i<arr1.length;i++){//将时间push到categories数组中,
//console.log('arr1['+i+']='+arr1[i]);
charts.xAxis.categories.push(arr1[i]);
}
var m;
for(m = 0;m<paraNum;m++){//0,1,2,3,多级Y轴---将yAxisObj对象push到charts.yAxis数组中,
var yAxisObj={"labels":{"format":'{value}°C',"style":{"color":"Highcharts.getOptions().colors["+m+"]"}},"title":{"text":arr0[m],"style":{"color":"Highcharts.getOptions().colors["+m+"]"}},"opposite":false} ;
/* console.log('************************************');
console.log('yAxisObj='+yAxisObj);
console.log('yAxisObj.labels='+yAxisObj.labels);
console.log('yAxisObj.labels.format='+yAxisObj.labels.format);
console.log('yAxisObj.labels.style='+yAxisObj.labels.style);
console.log('yAxisObj.labels.style.color='+yAxisObj.labels.style.color);
console.log('yAxisObj.title='+yAxisObj.title);
console.log('yAxisObj.title.text='+yAxisObj.title.text);
console.log('yAxisObj.title.style='+yAxisObj.title.style);
console.log('yAxisObj.title.style.color='+yAxisObj.title.style.color);
console.log('yAxisObj.opposite='+yAxisObj.opposite);
console.log('************************************'); */
if(m%2!=0){
yAxisObj.opposite=true;
}
charts.yAxis.push(yAxisObj);
var dataArray = "arr"+(m+2);
console.log("dataArray="+dataArray);
var seriesObj={"name":arr0[m],"type":"spline","yAxis":m,"data":eval(dataArray),"tooltip":{"valueSuffix":"°C"},"visible":false};
if(m==0){
seriesObj.visible=true;
}
/* console.log('************************************');
console.log('seriesObj='+seriesObj);
console.log('seriesObj.name='+seriesObj.name);
console.log('seriesObj.type='+seriesObj.type);
console.log('seriesObj.yAxis='+seriesObj.yAxis);
console.log('seriesObj.data='+seriesObj.data);
console.log('seriesObj.tooltip='+seriesObj.tooltip);
console.log('seriesObj.tooltip.valueSuffix='+seriesObj.tooltip.valueSuffix);
console.log('seriesObj.visible='+seriesObj.visible);
console.log('************************************'); */
charts.series.push(seriesObj);
}
/* console.log('************************************');
console.log('charts.yAxis='+charts.yAxis);
for(var i=0;i<paraNum;i++){
console.log('charts.yAxis['+i+'].labels='+charts.yAxis[i].labels);//预计undefined
console.log('charts.yAxis['+i+'].labels.format='+charts.yAxis[i].labels.format);
console.log('charts.yAxis['+i+'].title='+charts.yAxis[i].title);
console.log('charts.yAxis['+i+'].title.text='+charts.yAxis[i].title.text);
}
console.log('charts.series='+charts.series);
for(var i=0;i<paraNum;i++){
console.log('charts.series['+i+'].yAxis='+charts.series[i].yAxis);//预计undefined
console.log('charts.series['+i+'].name='+charts.series[i].name);
console.log('charts.series['+i+'].data='+charts.series[i].data);
}
console.log('************************************'); */
var options=new Highcharts.Chart(charts);
},
error:function(){
alert('ajax请求失败');
}
});
}
function timeStamp2String (time){//js timestamp转datetime
var datetime = new Date();
datetime.setTime(time);
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1;
var date = datetime.getDate();
var hour = datetime.getHours();
var minute = datetime.getMinutes();
var second = datetime.getSeconds();
// var mseconds = datetime.getMilliseconds();
return year + "-" + month + "-" + date+" "+hour+":"+minute+":"+second;
};
</script>
</body>
</html>