Highcharts 实现实时监控图表(x轴随着时间动态变化)

环境:Highcharts 5.0.6

第一:x轴是时间点(形如 23:12:29 格式)

第二:x轴是变化的

第三:x轴的值是从服务中获取

这里贴上最核心的逻辑(因为时间比较赶,没有深入研究官方文档,只经过测试,这里是核心)

大概实现逻辑,是通过

window.setInterval(getForm, 500);

定时的向服务器发送请求(getForm函数里面是个ajax请求),不断获取最新的数据点信息(包含x轴、y轴信息),将数据点插入图表数据集合中,然后重新渲染图表。

接着,上图中的函数getForm,内容如下:

var value = Number(data[i].c_tagval);
//alert(tval);
var createtime = data[i].c_createtime;
//获取服务器的数字型的时间,应为highcharts处理时间,用long,
createtime = parseInt(createtime);
console.info(createtime);

/*	
	//生成UI端自己的时间,这样做会和服务器的不一致
	var mydate = new Date();
	tm = mydate.getTime();
*/

// 第2个参数(是否重绘)个当添加多个值时,应设为false;第3个参数true时,添加时自动将第一个删除 
// 其实文档上说是可以传入多个值的,有待测试
series.addPoint([ createtime, value ], false, true);
//图表重新渲染
chart.redraw();

上面的代码是从服务器中获取的点值,createtime 是x坐标,value是y坐标;需要注意的是createtime 是要在x轴上,x轴的type属性是datetime,目前测试,时间只支持int,故需要将服务器的createtime (字符串)转成int(必须手动转换!!!),我这里使用

createtime = parseInt(createtime);

又由于我们的x轴格式是形如时:分:秒,故需要将控件的x轴进行如下设置:

扫描二维码关注公众号,回复: 6025025 查看本文章
xAxis : {
			type : 'datetime',
			title : {
				text : '时间'
			},
			labels : {
				formatter : function() {
					//获取当前轴的值
					var s = this.value;
					//浏览器上输出日志
					//console.info(s);
					
					var date = new Date(s);
            		return date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
            		
				}
			},
			showLastLabel : true,
			maxPadding : 0.05
		},

还有一点需要注意:

由于从服务器获取数据时,将新的点插入图表时,使用的

// 第2个参数(是否重绘)个当添加多个值时,应设为false;第3个参数true时,添加时自动将第一个删除 
					// 其实文档上说是可以传入多个值的,有待测试
					series.addPoint([ createtime, value ], false, true);

每添加一个新值,就会删除掉第一个值,这是第二个参数为true时的特性。

因为我们不能设为false,不然x轴的坐标会越来越密,这不是我们想要的。

但因为我们设为true了,所以图表初始状态时(图表渲染初期,还为从服务器获取值时),必须提前有一些无效的数据,让图表拥有一个默认的x轴个数,不然图表就永远只有刚刚从服务器获取的那一个点了。

初始化默认值的代码如下:

//设定报表对象的初始数据   
		series : [ {
			
			data : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0]
		
		}

下面列出所有js代码(复习时候,值关系核心逻辑即可,不要在意业务细节):

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>

<script type="text/javascript"
	src="${pageContext.request.contextPath}/util/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/util/Highcharts-5.0.6/highcharts.js"></script>
<script type="text/javascript"
	src="${pageContext.request.contextPath}/util/Highcharts-5.0.6/themes/dark-blue.js"></script>

</head>

<body>

	<div id="container"
		style="min-width: 310px; height: 400px; margin: 0 auto"></div>


</body>
<script type="text/javascript">
//<![CDATA[    


$(function() {


	//js定时函数的id值
	var intv;
	var chartType = [
		{	
			yAxis_min:100,yAxis_max:500,
			yAxis_tickInterval:50,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:200,
			yAxis_plotBands_high_from:400, yAxis_plotBands_high_to:500
		},{	
			yAxis_min:0,yAxis_max:80,
			yAxis_tickInterval:10,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:20,
			yAxis_plotBands_high_from:60, yAxis_plotBands_high_to:80
		},
		{	
			yAxis_min:0,yAxis_max:5,
			yAxis_tickInterval:0.5,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:2,
			yAxis_plotBands_high_from:4, yAxis_plotBands_high_to:5
		},{	
			yAxis_min:0,yAxis_max:5,
			yAxis_tickInterval:1,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:1,
			yAxis_plotBands_high_from:4, yAxis_plotBands_high_to:5
		},{	
			yAxis_min:0,yAxis_max:3,
			yAxis_tickInterval:0.1,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:0.5,
			yAxis_plotBands_high_from:2, yAxis_plotBands_high_to:3
		},{	
			yAxis_min:5,yAxis_max:20,
			yAxis_tickInterval:5,
			yAxis_plotBands_low_from:5, yAxis_plotBands_low_to:10,
			yAxis_plotBands_high_from:18, yAxis_plotBands_high_to:20
		}];

	//y轴低值区域的from
	var yAxis_plotBands_normal_from = '${min}';
	// y轴低值区域的to
	var yAxis_plotBands_normal_to = '${max}';
	
	//序号
	var index = '${chartType}';
	//y轴最小值	
	var yAxis_min = chartType[index-1].yAxis_min;
	// y轴最大值	
	var yAxis_max = chartType[index-1].yAxis_max;
	// y轴步长	
	var yAxis_tickInterval  = chartType[index-1].yAxis_tickInterval;
	
	//y轴低值区域的from
	var yAxis_plotBands_low_from =  chartType[index-1].yAxis_plotBands_low_from;
	// y轴低值区域的to
	var yAxis_plotBands_low_to = chartType[index-1].yAxis_plotBands_low_to;
	//y轴低值区域的from
	var yAxis_plotBands_high_from =  chartType[index-1].yAxis_plotBands_high_from;
	// y轴低值区域的to
	var yAxis_plotBands_high_to =  chartType[index-1].yAxis_plotBands_high_to;
	
	
	Highcharts.setOptions({
		global : {
			useUTC : false
		}
	});
	//声明报表对象   
	var chart = new Highcharts.Chart({
		chart : {
			//将报表对象渲染到层上   
			renderTo : 'container',
			defaultSeriesType : 'spline'
			
		}, //chart end  
		title : {
			text : '实时曲线'
		},
		yAxis : {
			title : {
				text : '值'+'${unit}'
			},
			labels : {
				formatter : function() {
					if (this.value > 400){
						return '<div style="color:red">' + this.value+ '</div>';
					}else if(this.value < 200){
						return '<div style="color:grey">' + this.value+ '</div>';
					}else if(this.value <= 360 && this.value>=340){
						return '<div style="color:green">' + this.value+ '</div>';
					}
								
					return this.value;
				}
			},
			//tickPositions: [-10,0, 10,20,30,40, 50,60,70,80,90,100,110,120]
			min : yAxis_min, //最小
			tickInterval : yAxis_tickInterval, //步长
			//max : 120,
			max:yAxis_max,
			/************************begin ************************/

			plotBands : [ {
				from : yAxis_plotBands_low_from,
				to : yAxis_plotBands_low_to,
				color : 'rgba(168, 255, 213, 0.3)',
				label : {
					text : '偏低',
					style : {
						color : '#ffffff'
					}
				}
			}, {
				from : yAxis_plotBands_normal_from,
				to : yAxis_plotBands_normal_to,
				color : 'rgba(68, 70, 213, 0.3)',
				label : {
					text : '正常',
					style : {
						color : '#41C639'
					}
				}
			}, {
				from : yAxis_plotBands_high_from,
				to : yAxis_plotBands_high_to,
				color : 'rgba(255, 97, 0, 0.3)',
				label : {
					text : '偏高',
					style : {
						color : '#FF0000'
					}
				}
			} ]

		/************************  end ************************/
		},
		xAxis : {
			type : 'datetime',
			title : {
				text : '时间'
			},
			labels : {
				formatter : function() {
					//获取当前轴的值
					var s = this.value;
					//浏览器上输出日志
					//console.info(s);
					
					var date = new Date(s);
            		return date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
            		
				}
			},
			showLastLabel : true,
			maxPadding : 0.05
		},
		legend : {
			enabled : false
		},
		tooltip : {
			headerFormat : '<br/>',
			pointFormat : '{point.x} : {point.y} '
		},
		/* plotOptions: {
		    spline: {
		        marker: {
		            enable: false
		        }
		    }
		}, */
		//设定报表对象的初始数据   
		series : [ {
			
			data : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0]
		
		} ]
	});
	//Highcharts.Chart end         

	//获取后台数据  
	function getForm() {
	
		var url =  "${pageContext.request.contextPath}/mydemo/xxx.do";
		$.ajax({
					type : "Post",
					//后台获取数据的函数,注意当对该页面重命名时,  
					//必须手动更改该选项  
					url : url,
					contentType : "application/json; charset=utf-8",
					dataType : "json",
					//成功获取数据  
					success : function(dataa) {
						addpoint(dataa.result);
					},
					//显示错误                                         
					error : function(err) {
						clearInterval(intv);
						///alert(err + "调用后台程序出现错误,请尝试刷新!");
					}
				});
	}
	
	function addpoint(data) {

		if (data && data.length > 0) {
		
				var series = chart.series[0];
				for(var i=0;i<data.length;i++)
				{
					var value = Number(data[i].c_tagval);
					//alert(tval);
					var createtime = data[i].c_createtime;
					//获取服务器的数字型的时间,应为highcharts处理时间,用long,
					createtime = parseInt(createtime);
					console.info(createtime);
					
					/*	
						//生成UI端自己的时间,这样做会和服务器的不一致
						var mydate = new Date();
						var a = mydate;
						a.setSeconds(a.getSeconds()+1);
						tm = a.getTime();
					*/
					
					// 第2个参数(是否重绘)个当添加多个值时,应设为false;第3个参数true时,添加时自动将第一个删除 
					// 其实文档上说是可以传入多个值的,有待测试
					series.addPoint([ createtime, value ], false, true);
					//图表重新渲染
					chart.redraw();
					
				}
				

		}
	}

	$(document).ready(function() {
		//只调用一次
		//getForm();
		//每隔3秒自动调用方法,实现图表的实时更新   
		intv = window.setInterval(getForm, 500);
	});
});

//]]>	
</script>
</html>

下面贴上从服务器获取的json的数据格式:

{    
    "message":"Update Successfully!",
    "result":[{
            "c_createtime":"1547005150000",
            "c_id":"123",
            "c_tagid":"1000",
            "c_tagval":"30",
            "c_wide1":"xxx",
            "c_wide2":"xxx",
            "c_wide3":"xxx"
    }],
    "status":"Success"
}

总结:

这里特殊说明,最初我试图使用规范的形如2019/10/10 23:21:30的字符串格式传送给js端处理,但是无效,倒不是实现不了,就是测试发现很复杂:

第一:字符串格式转js的对象日期,构造函数有两种:new Date('字符串')和new Date(多个字符串参数),只有传单纯的毫秒时是一个参数,且两种方式正好统一;其他格式的日期都和浏览器的本地化有关,反正浏览器不认识就返回给你NAN(又是罪恶的IE!!!,Firefox、chrome浏览器没问题,)

第二:即便你碰巧了,使用浏览器本地化格式的日期字符串格式,那么依然存在问题。那就是x轴的默认值无法转换成相应的的日期格式。

故我改成了直接传时间格式为毫秒的字符串。

updateDate:2019/01/10:

后期还发现个问题:

鼠标移动上去,发现x轴的值的日期的毫秒,不是和x轴显示的坐标一致,是日期的毫秒形式.

解决方案:

修改原有的tooltip属性:


		tooltip : {
			formatter: function () {
				var date = new Date(this.x);
				var a = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
				//console.info(a);
        		return "( "+a+" , "+this.y+" )";
				//var s = '<b>' + this.x + '---xx</b>';
				//return s;
			},
			shared: true,
			//pointFormat : '{point.x} :: {point.y} '
			headerFormat : '<br/>',
		},

而且发现:原有的xAxis属性中的labels没啥卵用,已经被注视掉了,其他没变化:

xAxis : {
			type : 'datetime',
			title : {
				text : '时间'
			},
			/* 
			//没啥卵用
			labels : {
				formatter : function() {
					//获取当前轴的值
					var createtime = this.value;
				
					createtime = parseInt(createtime);
					console.info(createtime);
					
					var date = new Date(createtime);
            		return date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
            		
				}
			},  */
			showLastLabel : true,
			maxPadding : 0.05
		},

贴出所有代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>

<script type="text/javascript"
	src="${pageContext.request.contextPath}/util/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/util/Highcharts-5.0.6/highcharts.js"></script>
<script type="text/javascript"
	src="${pageContext.request.contextPath}/util/Highcharts-5.0.6/themes/dark-blue.js"></script>

</head>

<body>

	<div id="container"
		style="min-width: 310px; height: 400px; margin: 0 auto"></div>


</body>
<script type="text/javascript">
//<![CDATA[    


$(function() {

	
	//js定时函数的id值
	var intv;
	var chartType = [
		{	
			yAxis_min:100,yAxis_max:500,
			yAxis_tickInterval:50,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:200,
			yAxis_plotBands_high_from:400, yAxis_plotBands_high_to:500
		},{	
			yAxis_min:0,yAxis_max:80,
			yAxis_tickInterval:10,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:20,
			yAxis_plotBands_high_from:60, yAxis_plotBands_high_to:80
		},
		{	
			yAxis_min:0,yAxis_max:5,
			yAxis_tickInterval:0.5,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:2,
			yAxis_plotBands_high_from:4, yAxis_plotBands_high_to:5
		},{	
			yAxis_min:0,yAxis_max:5,
			yAxis_tickInterval:1,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:1,
			yAxis_plotBands_high_from:4, yAxis_plotBands_high_to:5
		},{	
			yAxis_min:0,yAxis_max:3,
			yAxis_tickInterval:0.1,
			yAxis_plotBands_low_from:0, yAxis_plotBands_low_to:0.5,
			yAxis_plotBands_high_from:2, yAxis_plotBands_high_to:3
		},{	
			yAxis_min:5,yAxis_max:20,
			yAxis_tickInterval:5,
			yAxis_plotBands_low_from:5, yAxis_plotBands_low_to:10,
			yAxis_plotBands_high_from:18, yAxis_plotBands_high_to:20
		}];

	//y轴低值区域的from
	var yAxis_plotBands_normal_from = '${min}';
	// y轴低值区域的to
	var yAxis_plotBands_normal_to = '${max}';
	
	//序号
	var index = '${chartType}';
	//y轴最小值	
	var yAxis_min = chartType[index-1].yAxis_min;
	// y轴最大值	
	var yAxis_max = chartType[index-1].yAxis_max;
	// y轴步长	
	var yAxis_tickInterval  = chartType[index-1].yAxis_tickInterval;
	
	//y轴低值区域的from
	var yAxis_plotBands_low_from =  chartType[index-1].yAxis_plotBands_low_from;
	// y轴低值区域的to
	var yAxis_plotBands_low_to = chartType[index-1].yAxis_plotBands_low_to;
	//y轴低值区域的from
	var yAxis_plotBands_high_from =  chartType[index-1].yAxis_plotBands_high_from;
	// y轴低值区域的to
	var yAxis_plotBands_high_to =  chartType[index-1].yAxis_plotBands_high_to;
	
	
	Highcharts.setOptions({
		global : {
			useUTC : false
		}
	});
	//声明报表对象   
	var chart = new Highcharts.Chart({
		chart : {
			//将报表对象渲染到层上   
			renderTo : 'container',
			defaultSeriesType : 'spline'
			
		}, //chart end  
		title : {
			text : '实时曲线'
		},
		yAxis : {
			title : {
				text : '值'+'${unit}'
			},
			labels : {
				formatter : function() {
					if (this.value > 400){
						return '<div style="color:red">' + this.value+ '</div>';
					}else if(this.value < 200){
						return '<div style="color:grey">' + this.value+ '</div>';
					}else if(this.value <= 360 && this.value>=340){
						return '<div style="color:green">' + this.value+ '</div>';
					}
								
					return this.value;
				}
			},
			//tickPositions: [-10,0, 10,20,30,40, 50,60,70,80,90,100,110,120]
			min : yAxis_min, //最小
			tickInterval : yAxis_tickInterval, //步长
			//max : 120,
			max:yAxis_max,
			/************************begin ************************/

			plotBands : [ {
				from : yAxis_plotBands_low_from,
				to : yAxis_plotBands_low_to,
				color : 'rgba(168, 255, 213, 0.3)',
				label : {
					text : '偏低',
					style : {
						color : '#ffffff'
					}
				}
			}, {
				from : yAxis_plotBands_normal_from,
				to : yAxis_plotBands_normal_to,
				color : 'rgba(68, 70, 213, 0.3)',
				label : {
					text : '正常',
					style : {
						color : '#41C639'
					}
				}
			}, {
				from : yAxis_plotBands_high_from,
				to : yAxis_plotBands_high_to,
				color : 'rgba(255, 97, 0, 0.3)',
				label : {
					text : '偏高',
					style : {
						color : '#FF0000'
					}
				}
			} ]

		/************************  end ************************/
		},
		xAxis : {
			type : 'datetime',
			title : {
				text : '时间'
			},
			/* 
			//没啥卵用
			labels : {
				formatter : function() {
					//获取当前轴的值
					var createtime = this.value;
				
					createtime = parseInt(createtime);
					console.info(createtime);
					
					var date = new Date(createtime);
            		return date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
            		
				}
			},  */
			showLastLabel : true,
			maxPadding : 0.05
		},
		
		legend : {
			enabled : false
		},
		
		tooltip : {
			formatter: function () {
				var date = new Date(this.x);
				var a = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
				//console.info(a);
        		return "( "+a+" , "+this.y+" )";
				//var s = '<b>' + this.x + '---xx</b>';
				//return s;
			},
			shared: true,
			//pointFormat : '{point.x} :: {point.y} '
			headerFormat : '<br/>',
		},
		/* plotOptions: {
		    spline: {
		        marker: {
		            enable: false
		        }
		    }
		}, */
		//设定报表对象的初始数据   
		series : [ {
			
			data : [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0]
		
		} ]
	});
	//Highcharts.Chart end         

	//获取后台数据  
	function getForm() {
	
		var url =  "${pageContext.request.contextPath}/mydemo/xx.do";
		$.ajax({
					type : "Post",
					//后台获取数据的函数,注意当对该页面重命名时,  
					//必须手动更改该选项  
					url : url,
					contentType : "application/json; charset=utf-8",
					dataType : "json",
					//成功获取数据  
					success : function(dataa) {
						addpoint(dataa.result);
					},
					//显示错误                                         
					error : function(err) {
						clearInterval(intv);
						///alert(err + "调用后台程序出现错误,请尝试刷新!");
					}
				});
	}
	
	function addpoint(data) {

		if (data && data.length > 0) {
		
				var series = chart.series[0];
				for(var i=0;i<data.length;i++)
				{
					var value = Number(data[i].c_tagval);
				
					var createtime = data[i].c_createtime;
					//获取服务器的数字型的时间,应为highcharts处理时间,用long,
					createtime = parseInt(createtime);
					//console.info('---'+createtime);
					
					
						//生成UI端自己的时间,这样做会和服务器的不一致
						//var mydate = new Date();
						//createtime = mydate.getTime(); 
					
					
					// 第2个参数(是否重绘)个当添加多个值时,应设为false;第3个参数true时,添加时自动将第一个删除 
					// 其实文档上说是可以传入多个值的,有待测试
					series.addPoint([ createtime, value ], false, true);
					//图表重新渲染
					chart.redraw();
					
				}
				

		}else{
			if(pagenum > 3){
				pagenum = 0;
			}
		}
	}

	$(document).ready(function() {
		//只调用一次
		//getForm();
		//每隔3秒自动调用方法,实现图表的实时更新   
		intv = window.setInterval(getForm, 500);
	});
});

//]]>	
</script>
</html>

猜你喜欢

转载自blog.csdn.net/rainyspring4540/article/details/86215137
今日推荐