对于使用X轴上的日期时间的Highchart折线图,如何使用一个pointInterval
的数据初始呈现图表,并使用另一个动态更新图表?
对于我的情况,初始渲染将使用恰好200个样本而不管持续时间。例如,假设给定图表的持续时间为1周。初始页面将接收200个数据点,相隔3,024秒(7 * 24 * 60 * 60/200)。然后,它将每隔60秒通过Ajax动态更新。
我尝试了多种方法,但是,Ajax 60秒刻度产生与初始页面3,024秒刻度相同的更改,或者最初创建的图表刻度更改或某些其他不期望的结果。该图表应该主要保持不变,但会使用新收到的Ajax数据慢慢更新。
以下https://jsbin.com/zuboyeh/edit?html,output显示了其中一些尝试。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Highcharts</title>
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script type="text/javascript">
$(function() {
/*
Total of 6 options.
Using pointAdd or pointUpdate.
Also, three options this way
Option 1. Pre-load w/o time, change pointInterval, then continue with no time. Doesn't work as it changes past date formats
Option 2. Pre-load w/o time, then continue with time.
Option 3. Pre-load w/ time, then continue with time.
*/
//initially page will display daily data for one month
var numberOfDatapointsToDisplay=200; //Given
var chartDuration = 7*24*60*60; //One week given resulting in 60,4800 seconds
var secondsInterval = chartDuration/numberOfDatapointsToDisplay; //3024 seconds
var pointInterval = 1000*secondsInterval; //ms
var tickInterval = null; //tickInterval is the interval of the tick marks in axis units. Not sure how to handle
var secondsIntervalAjax=60; //One minute given for ajax request time
var currentTime=new Date().getTime()/1000; //UTC time
var secondsStart=currentTime - numberOfDatapointsToDisplay*secondsInterval; //Start a week in the past and then populate upon page load
var pointStart = 1000*secondsStart; //ms
//Get initial data
var data1=[],data2=[],data3=[];
for (var i = 0; i < numberOfDatapointsToDisplay; i++) {
var v=gv(pointInterval/1000); //Data simulator for this example
data1[i]=v; //attempt using a single value
data2[i]=[secondsStart,v]; //attempt using cartesian values
secondsStart+=secondsInterval;
}
$("#addPoint").click(function() {
//Simulate ajax request using addPoint()
currentTime+=secondsIntervalAjax;
var v=gv(secondsIntervalAjax);
chart1.series[0].addPoint(v, true, true); //attempt using a single value
chart2.series[0].addPoint([currentTime,v], true, true); //attempt using cartesian values
});
$("#updateSeries").click(function() {
//Simulate ajax request using update()
currentTime+=secondsIntervalAjax;
var v=gv(secondsIntervalAjax);
data1.push(v);
data2.push([currentTime,v]);
chart1.series[0].update({data: data1}); //attempt using a single value
chart2.series[0].update({data: data2}); //attempt using cartesian values
});
$("#changePointInterval").click(function() {
//Try changing the pointInterval used for the initial page data and ajax data
chart1.series[0].update({pointInterval: secondsIntervalAjax*1000});
chart2.series[0].update({pointInterval: secondsIntervalAjax*1000});
})
var chart1 = new Highcharts.Chart({
chart: {
type: "line",
renderTo: 'container1'
},
xAxis: {
type: "datetime",
//tickInterval: tickInterval,
//tickPixelInterval: 50
},
series: [
{name: 'SeriesName', data: data1},
],
plotOptions: {
series: {
pointStart: pointStart,
pointInterval: pointInterval,
}
},
});
var chart2 = new Highcharts.Chart({
chart: {
type: "line",
renderTo: 'container2'
},
xAxis: {
type: "datetime",
//tickInterval: tickInterval,
dateTimeLabelFormats: {month: '%e. %b',year: '%b'},
tickPixelInterval: 50
},
series: [
{name: 'SeriesName', data: data2},
],
plotOptions: {
spline: {
marker: {
enabled: true
}
}
},
});
function gv(s) {
//Data simulator for new value after s seconds
if ( typeof this.v == 'undefined' ) {
this.v = 100;
}
this.v=this.v+50*numberOfDatapointsToDisplay*(Math.random()-.5) * s/chartDuration;
return this.v;
}
});
</script>
</head>
<body>
<button id="addPoint">addPoint</button>
<button id="updateSeries">updateSeries</button>
<button id="changePointInterval">changePointInterval</button>
<div id="container1" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
<div id="container2" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
</body>
</html>
答案 0 :(得分:1)
每个系列只能定义一个pointInterval
。
这个问题有2个最简单的解决方案:
<强> 1。为新值添加另一个链接系列
linkedTo:previous
会导致图例切换对两个系列都有效。更改第二个系列的颜色,使其看起来与第一个系列完全相同。使用基本系列中的最后一个值设置pointStart
:
events: {
load: function() {
var points = this.series[0].points,
lastPoint = points[points.length - 1];
this.series[1].update({
pointStart: lastPoint.x,
color: this.series[0].color
});
}
}
(...)
series: [{
name: 'SeriesName',
data: data1
}, {
name: 'SeriesName', // same name as the previous series
pointInterval: secondsIntervalAjax * 10000, // 10 times bigger to see results faster
linkedTo: ':previous',
marker: {
enabled: false
}
}]
现场演示: http://jsfiddle.net/kkulig/gtsw8t3q/
<强> 2。计算并明确地为每个点分配x值
在这种情况下,不需要pointInterval
和pointStart
。