Javascript 同一系列中具有相同x轴的点的流动合并
我目前正在使用highstock根据一天中的时间(然后实时更新)绘制可用项目的总数 如果项目总数同时发生两次变化,在highstock中,我会得到一个垂直的差异条: 因此,在我的示例图像中,我们从4299个项目开始,然后删除53个项目,添加50个项目(技术上是同时进行的,但这是两个不同的事务,是两点)。净差额为-3。(或者换句话说,我得到{x:5:44:15和y:4246,change:-53},{x:5:44:15,y:4296,change:50}) 因此,我的问题是: 在highstock中,是否可以合并这些点以去除垂直条并使用4296作为显示值?我希望随后可以使用工具提示格式化程序循环“this.points”,并在工具提示中显示-53和50的变化,以便用户可以看到导致-3净变化的原因 如果这是不可能的,我将自己合并这些点,并传递点中的所有相关信息,以生成我想要的工具提示(和图表外观),但我想看看是否可以首先利用highstock的所有功能,并将这些点分开 谢谢 编辑::Javascript 同一系列中具有相同x轴的点的流动合并,javascript,highcharts,highstock,Javascript,Highcharts,Highstock,我目前正在使用highstock根据一天中的时间(然后实时更新)绘制可用项目的总数 如果项目总数同时发生两次变化,在highstock中,我会得到一个垂直的差异条: 因此,在我的示例图像中,我们从4299个项目开始,然后删除53个项目,添加50个项目(技术上是同时进行的,但这是两个不同的事务,是两点)。净差额为-3。(或者换句话说,我得到{x:5:44:15和y:4246,change:-53},{x:5:44:15,y:4296,change:50}) 因此,我的问题是: 在highstoc
new Highcharts.StockChart({
chart : {
renderTo : 'realTimeChart',
zoomType: 'x',
backgroundColor: '#feffdd',
style: {
fontFamily: 'Segoe UI'
},
type: 'spline'
},
plotOptions: {
area: { animation: false },
arearange: { animation: false },
areaspline: { animation: false },
areasplinerange: { animation: false },
bar: { animation: false },
column: { animation: false },
columnrange: { animation: false },
gauge: { animation: false },
line: { animation: false },
pie: { animation: false },
scatter: { animation: false },
series: { animation: false },
spline: { animation: false }
},
xAxis: {
ordinal: false
},
tooltip: {
animation: false,
formatter: function() {
var p = '';
p += '<span style="font-size: 9px;">' + Highcharts.dateFormat('%A, %b %e, %Y %H:%M:%S', this.x) +'</span><br/>';
$.each(this.points, function(i, point){
p += '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>'+ this.y +'</b>';
if (point.point.where) {
p += '<br />' + point.point.where + ' changed by ' + point.point.change + (point.point.who ? ' (' + point.point.who + ')' : '');
}
});
return p;
}
},
rangeSelector: {
buttons: [{
count: 30,
type: 'minute',
text: '30M'
}, {
count: 1,
type: 'hour',
text: '1H'
}, {
count: 6,
type: 'hour',
text: '6H'
}, {
type: 'all',
text: 'Day'
}],
inputEnabled: false,
selected: 1
},
exporting: {
enabled: false
},
series : [{
name : 'Available',
data : data,
lineWidth: 1,
states: {
hover: {
enabled: false
}
}
}]
我只是想了解一下我是如何轻松绕过这个问题的。我决定不按秒排列,而是将各点按最接近的分钟四舍五入排列(因此我有几段分钟) 然后,对于每个点,我将该分钟块中包含的实际点数组作为新参数传递,并更新该分钟块的y值。然后,我使用工具提示格式化程序显示该分钟块内的所有更改及其实际更改时间。这给了我一个更流畅的图形,而不是相同x轴的所有这些硬垂直点 为了方便地更改特定x轴点的数据点,我在序列中保留了一个单独的分钟块位置数组。highcharts的数据数组,这样,如果我需要更新块,我就可以准确地知道时间序列的位置 以下是我完成任务的方式: 我创建引用数组:
var pointIndex = {};
我根据当天的历史数据创建了初始数据系列(通过ajax拉入):
因此,actual_time是自epoch以来的毫秒数(发生偶数更改时),然后我将其四舍五入到最接近的分钟以获得分钟时间块,change是一个参数,它将保存所有实际点,以便在工具提示中显示
因此,当我添加一个新点时,我会检查分钟块是否存在,如果不存在,则添加一个新点,否则更新一个旧点:
var time = (new Date()).getTime();
var point = Math.floor(time / 60000) * 60000;
if (pointIndex[point]) {
var change = chart.series[0].data[pointIndex[point]].change;
change.push({when: time});
chart.series[0].data[pointIndex[point]].update({x: point, y: items_available, change: change});
} else {
pointIndex[point] = chart.series[0].data.length;
chart.series[0].addPoint({x: point, y: items_available, change: [{when: time}]}, false, false);
}
(在所有情况下,我都会在完成点更新后进行实际图表刷新。)
希望这将有助于其他人谁发现自己在相同的位置
编辑::(忘记了格式化程序):
工具提示:{
动画:错,
格式化程序:函数(){
var p='';
p++=''+Highcharts.dateFormat(“%A,%b%e,%Y%H:%M',this.x)+'
';
$.each(this.points,function(i,point){
p+=''+this.series.name+':''+this.y+'';
如果(点.点.更改){
对于(变量j=0;j 更改时间:'+新日期(point.point.Change[j].when).toTimeString();
}
}
});
返回p;
}
}
您尝试过什么?给我们看一些代码。如何获取/设置highcharts的数据源?您可能希望提前预处理这些数据以说明这一点。HighCharts只接收您发送的数据。当然,您可以在HighCharts中执行此操作,但它并不是专门为此而设计的,而且您编写的代码将比您需要的多得多。也就是说你可以(看起来)按秒分组数据?试试看。添加了更多代码来显示设置@Shmidty,这更像是一个“是否可能”的问题,因为我知道我怎样才能把它全部合并在一起。但是,如果这是highcharts的一个功能,那么我宁愿使用它,也不愿自己实现点的合并。@wergeld-是的,看起来我必须自己进行合并(技术上是毫秒而不是秒)。但是你回答了我的想法,所以谢谢!您可以使用javascript的一个常见技巧,将x值用作对象中的属性键,y值作为属性值。因此,迭代数据,测试该键中是否有内容,如果有,进行调整,否则将其转储并继续。
var data = [];
var time = Math.floor(actual_time / 60000) * 60000;
pointIndex[time] = data.push({x: time, y: items_available, change: [{when: actual_time}]});
var time = (new Date()).getTime();
var point = Math.floor(time / 60000) * 60000;
if (pointIndex[point]) {
var change = chart.series[0].data[pointIndex[point]].change;
change.push({when: time});
chart.series[0].data[pointIndex[point]].update({x: point, y: items_available, change: change});
} else {
pointIndex[point] = chart.series[0].data.length;
chart.series[0].addPoint({x: point, y: items_available, change: [{when: time}]}, false, false);
}
tooltip: {
animation: false,
formatter: function() {
var p = '';
p += '<span style="font-size: 9px;">' + Highcharts.dateFormat('%A, %b %e, %Y %H:%M', this.x) +'</span><br/>';
$.each(this.points, function(i, point){
p += '<span style="color:' + this.series.color + '">' + this.series.name + '</span>: <b>'+ this.y +'</b>';
if (point.point.change) {
for(var j = 0; j < point.point.change.length; ++j) {
p += '<br />Change at: ' + new Date(point.point.change[j].when).toTimeString();
}
}
});
return p;
}
}