Render chart only once with multiple events : Highcharts - javascript
So what I have is a chart in which I have events function which loads data for multiple sets.
suppose I have data of 3000 points. The first data set renders the first 1000 points and after that second data set renders 2000 points.
for which I am calling my 'events' function .
but the problem arises that after showing the first 1000 set of data. The chart starts from the begining.
I don't want that.
That's why I need a solution so that my Highchart's chart render only once and the event function loads continuously.
Here's a snip of my Highchart's js
Highcharts.chart("chartcontainer", { // make thsi chart load only once.
chart: {
type: 'line',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
//Load this event function as the data updates
events: {
load: function() {
var series = this.series[0],
chart = this;
setInterval(function() {
//some logic regarding the chart
//..
v = {
y: y,
x: x
};
console.log("V value", v);
series.addSeries(v, false, true);
counter++;
localcounter++;
} else
{
oldcounter=counter;
flagToreload=1;
}
}, 1000/130);
setInterval(function() {
chart.redraw(false);
}, 100);
}
}
},
time: {
useUTC: false
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'Value',
gridLineWidth: 1
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
gridLineWidth: 1
},
tooltip: {
headerFormat: '<b>{series.name}</b><br/>',
pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}'
},
exporting: {
enabled: false
},
series: [{
animation: false,
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = counter,
i;
for (i = -1000; i <= 0; i += 1) {
data.push([
counter,
null
]);
}
return data;
}())
}]
});
You can use:
addPoint method:
chart: {
events: {
load: function() {
var newData,
chart = this,
series = chart.series[0];
setInterval(function() {
newData = getRandomData();
newData.forEach(function(el) {
series.addPoint(el, false);
});
chart.redraw();
}, 2000);
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/2a8qswhf/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#addPoint
setData method:
chart: {
events: {
load: function() {
var newData,
chart = this,
combinedData,
series = chart.series[0];
setInterval(function() {
newData = getRandomData();
combinedData = series.userOptions.data.concat(newData);
series.setData(combinedData);
}, 2000);
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/Lmsk8yw9/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#setData
Related
Stop Highchart when end of the Array element reached
So What I am trying to Create is a Chart in which around 130 points data are flowing in a single second time. Now, Suppose I Have an array of 1000 elements which I want to render in Highchart. I am able to render the Highchart with the 1000 elements of array, but the problem is that after the end of the array, the Highchart is not stopping. it keeps running. I just want to stop the Highchart when it reaches end of the array. Here is the Code that I have tried var data = [7,10,8,6,8,2,5,2,2,2,3,4,4,10,6,10,5,10,0,2,9,5,7,0,5,0,5,7,8,7,5,1,9,1,5,7,10,3,7,0,2,10,8,8,1,1,0,7,6,3,1,10,0,8,3,5,5,10,3,8,4,0,3,5,8,7,0,0,0,8,7,3,2,1,0,6,7,7,3,7,5,0,1,0,0,4,9,4,4,3,0,2,10,9,0,2,7,6,5,9,0,6,7,9,0,6,2,7,1,6,5,1,3,1,0,5,0,4,2,7,2,0,7,0,3,10,6,3,4,9,9,10,10,9,5,9,8,5,3,2,5,9,5,10,10,7,8,3,8,9,5,3,9,0,1,2,6,4,1,9,0,5,0,5,6,4,1,1,3,8,2,0,7,6,4,0,6,5,5,6,4,6,6,3,3,5,5,8,7,3,4,7,5,6,1,4,2,4,7,9,8,4,0,3,8,6,2,6,10,8,10,1,10,8,6,8,8,3,8,7,8,6,7,10,9,10,0,7,7,8,1,10,1,4,7,10,7,0,9,6,3,3,3,1,4,3,4,5,0,5,9,0,6,1,8,5,1,8,9,4,0,4,5,4,3,8,2,10,5,9,4,9,5,3,6,5,7,2,2,7,1,1,9,7,4,1,7,5,2,10,6,4,3,5,7,2,4,5,7,3,2,0,8,5,5,7,8,2,9,5,9,1,2,0,7,8,10,5,6,9,2,5,1,9,4,0,7,4,4,7,10,0,8,6,0,6,4,4,8,3,9,1,3,0,0,4,4,2,5,3,3,6,1,4,6,6,4,9,7,0,2,2,1,2,2,6,2,0,2,5,7,8,8,1,7,3,9,0,0,0,9,4,9,8,9,7,10,8,2,0,5,10,10,0,1,7,5,9,2,8,10,10,4,6,6,6,10,10,5,1,5,2,1,9,3,2,5,3,1,3,10,7,1,3,5,3,0,6,7,5,1,10,5,9,0,9,2,3,0,10,0,6,9,8,3,8,7,0,10,4,2,2,5,6,7,0,10,10,9,9,8,6,10,5,9,0,6,4,8,5,0,4,4,4,1,8,3,0,9,3,3,9,1,5,0,10,1,1,3,10,6,5,8,0,6,5,2,7,10,4,2,0,10,1,7,6,2,0,1,6,10,10,6,6,10,1,4,7,5,6,5,4,1,5,6,9,1,8,4,7,2,8,5,9,7,3,9,2,2,8,10,6,10,10,7,8,7,2,6,8,7,4,6,1,5,9,2,0,5,4,4,0,4,5,7,2,3,8,9,1,0,8,6,10,8,3,7,3,3,6,7,2,7,6,6,2,8,6,9,6,8,5,4,8,4,6,7,9,8,7,8,5,8,2,0,8,5,0,5,2,8,4,7,0,7,1,4,8,10,8,2,5,10,9,1,9,3,0,6,9,2,10,5,1,4,0,4,9,1,1,3,5,0,5,5,2,5,1,1,7,0,2,6,8,10,7,9,3,0,9,4,2,4,6,2,2,9,2,7,3,6,6,9,2,2,0,2,9,1,5,7,10,10,1,8,5,9,9,4,1,7,1,0,0,6,7,7,7,2,9,9,2,10,5,4,2,3,10,9,9,7,1,1,6,8,4,9,6,7,4,9,4,2,7,6,2,6,0,1,5,5,8,9,5,1,7,8,7,3,2,3,1,1,2,5,6,4,10,8,10,3,3,1,0,6,7,0,7,4,8,4,7,6,0,7,1,2,3,10,4,1,10,7,9,4,7,7,10,10,10,6,8,9,7,3,10,9,0,3,6,2,10,5,3,6,8,5,0,2,3,1,6,9,10,9,10,7,5,8,7,4,4,3,10,2,3,4,3,10,8,5,9,8,5,6,2,4,9,1,5,0,7,1,1,4,4,10,4,7,8,8,9,7,1,9,5,5,4,3,0,0,9,5,6,3,3,4,6,1,2,6,2,8,4,10,0,9,1,10,2,7,3,6,3,9,2,3,5,7,8,1,1,9,3,4,6,7,6,2,2,8,0,10,3,3,5,7,4,1,3,9,5,4,3,3,2,9,8,7,8,7,6,8,7,7,1,2,10,10,2,9,3,2,3,2,9,9,0,3,0,4,9,6,0,1,6,9,5,8,7,9,5,6,8,3,5,3,4,9,8,0,3,4,8,6,9,4,7,1,9,8,0,4,8,1,0,7,3,3,1,6,9,9,5,4,3,8,8,9,10,4,9,0,7,8,6,9,8,4,10,4,1,2,5,4,0,6,4,1]; var json_array = data ; var i = 0; function next() { return json_array[i++]; // i++; } Highcharts.chart('container', { chart: { type: 'line', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events: { load: function() { // set up the updating of the chart each second var series = this.series[0], chart = this; var count = 0 ; setInterval(function() { var x = (new Date()).getTime(), // current time y =next(); console.log(y) ; series.addPoint([x, y], false, true); chart.redraw(false); }, 1000/130); } } }, time: { useUTC: false }, title: { text: 'ECG Graph Plot From MySQl Data' }, xAxis: { type: 'datetime', labels: { enabled: false }, tickPixelInterval: 150 }, yAxis: { //max: 1.5, //min: -1.5, title: { text: 'Value' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { headerFormat: '<b>{series.name}</b><br/>', pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}' }, legend: { enabled: false }, exporting: { enabled: false }, series: [{ animation: false, name: 'ECG Graph Plot From MySQl Data', dataGrouping: { enabled: false }, data: (function() { // generate an array of random data var data = [], time = (new Date()).getTime(), i; for (i = -1000 ; i <= 0; i += 1) { data.push([ time + i * 10, null ]); } return data; }()) }] }); I Have also created a Fiddle for it as you can see below. https://jsfiddle.net/abnitchauhan/toqaxLj7/
Just clear Interval when it reached the last element of the array. check out following code. var draw = setInterval(function() { var x = (new Date()).getTime(), // current time y =next(); console.log(y) ; if (i == data.length) { clearInterval(draw); return; } series.addPoint([x, y], false, true); chart.redraw(false); }, 1000/130); here is the fiddle code link. https://jsfiddle.net/geekcode/8nL53x01/1/
Highcharts Not displaying function's data values
i Have created a Highchart using the Following Highchart's Demo: https://www.highcharts.com/demo/dynamic-update Now What I did I created my Own function to add dynamic values to the Chart. I created a function to get the dynamic data from a particular php file whose data changes on every page load event. I am getting the data values in the getData function console.log Here is the Script That I am using. <script type="text/javascript"> $(document).ready(function(){ function getData(){ $.ajax({ type: 'GET', url: 'data.php', success: function(data){ // var number = document.write(data) ; console.log(data); return data ; } }) ; } Highcharts.chart('chart', { chart: { type: 'spline', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events: { load: function () { // set up the updating of the chart each second var series = this.series[0]; setInterval(function () { var x = (new Date()).getTime(), // current time y = getData(); console.log(y); series.addPoint([x, y], true, true); }, 1000); } } }, time: { useUTC: false }, title: { text: 'Live random data' }, xAxis: { type: 'datetime', tickPixelInterval: 150 }, yAxis: { title: { text: 'Value' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { headerFormat: '<b>{series.name}</b><br/>', pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}' }, legend: { enabled: false }, exporting: { enabled: false }, series: [{ name: 'Random data', data: (function () { // generate an array of random data var data = [], time = (new Date()).getTime(), i; for (i = -19; i <= 0; i += 1) { data.push({ x: time + i * 1000, y: getData() }); } return data; }()) }] }); }); </script> Now as you can see that I have created a getData function and getting the data value in return. On console log under the getData function, I am getting integer Value in return every one second. the problem is that under the Highchart's function, I am not able to get the data values using getData function, it's returning undefined in the console . Highchart's is running but it does not show any data points. it is moving but without showing any data points. Please correct me in the area , where I am doing wrong. Any help is appreciated. Thanks
ajax calls are run asynchronously so you cant really return data from it. instead you should render chart inside the ajax success function. A good example is here already. https://www.highcharts.com/docs/working-with-data/live-data Basically 1. point on load to call a function getData 2. in Getdata call ajax function. 3. in success of ajax render chart with new data. document.addEventListener('DOMContentLoaded', function() { chart = Highcharts.chart('container', { chart: { type: 'spline', events: { load: requestData } }, title: { text: 'Live random data' }, xAxis: { type: 'datetime', tickPixelInterval: 150, maxZoom: 20 * 1000 }, yAxis: { minPadding: 0.2, maxPadding: 0.2, title: { text: 'Value', margin: 80 } }, series: [{ name: 'Random data', data: [] }] }); }); /** * Request data from the server, add it to the graph and set a timeout * to request again */ function requestData() { $.ajax({ url: 'live-server-data.php', success: function(point) { var series = chart.series[0], shift = series.data.length > 20; // shift if the series is // longer than 20 // add the point chart.series[0].addPoint(point, true, shift); // call it again after one second - add this if you want to auto refresh // setTimeout(requestData, 1000); }, cache: false }); }
Multiple Charts not moving in sync at random times when adding value on interval
I am trying to create dynamic number of series from UI. Upon selection, backend updates one entry at the time. While the graphs are running fine at most times. At some random time the two series move out of sync as in http://jsfiddle.net/cRgUr/ and come back in sync after few seconds. I have referred following links for resolution but still see the issue. Chart not moving fluently when adding value to two lines on interval and Updating spline chart two lines on top of eachother Below is the code snippet : function getInitialData(series){ var arrayOfValues=[]; $http({ mode:'cors', method:'GET', url: '/getData', headers: { 'Content-Type':'application/json' }, cache: false, }).success(function(data) { arrayOfValues.push(/*populated by backend*/); // E.g values for y for number of series selected. If 2 series are to be drawn, at a time this array will contain arrayOfValue[0]= y value for series 1, arrayOfValue[1]=y value for series 2 } drawgraph(series,arrayOfValues,newWidgetMetrics/*widget selected from UI*/); } ).error(function(data) { }); function drawgraph(series,arrayOfValues,newWidgetMetrics1){ var time = (new Date()).getTime(); for(let p=0;p<arrayOfValues.length;p++){ if(p<arrayOfValues.length-1){ series[p].addPoint([time,arrayOfValues[p]] ,false , (series[0].data.length >= 20));// set false for all series but the last, with an animation where we want the line to start plotting after 20 seconds } else{ series[p].addPoint([time,arrayOfValues[p]] , true , (series[0].data.length >= 20));// set true for only the last series, with an animation where we want the line to start plotting after 20 seconds } chart.redraw(); } arrayOfValues=[]; } dataSeries=function(){ for(var i=0;i<length;i++){ var obj={}; obj.type="line"; obj.data=getData(); obj.boostThreshold=60; obj.name=newWidgetLegends[i]; tArray.push(obj); } return tArray; } func_plot(); function func_plot(){ $(document).ready(function() { Highcharts.setOptions({ global: { useUTC: false } }); chart=Highcharts.chart(divId, { chart: { height:'38%', zoomType: 'x', type: 'spline', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events: { load: function () { maxSamples = 60, counter = 0; // set up the updating of the chart each second var ser = this.series; // setTimeout(function () { setInterval(function (){ window['arr' + count]=[]; getInitialData(ser); }, 1000); }, 2000); } } }, title: { text: '', style: { display: 'none' } }, exporting: { buttons: { contextButton: { y:screen.height*-0.02 } } }, plotOptions: { line: { marker: { enabled: false } }, events: { legendItemClick: function () { return false; } } }, xAxis: { type: 'datetime', ordinal:false, labels: { format: '{value:%M:%S}' }, tickInterval: 10000, title: { text: newWidetXLabel, marginBottom: 100 } }, yAxis: { title: { text:newWidetYLabel, min: 0, max:10 }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, legend: { title: { text: '', style: { fontStyle: 'italic' } }, layout: 'horizontal', align: 'right', verticalAlign: 'top', x: -30, y: -17 }, boost: { seriesThreshold:2, useGPUTranslations: true }, credits: { enabled: false }, tooltip: { formatter: function () { return Highcharts.dateFormat('%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 2); } }, series: dataSeries() }); }); } $(window).resize(function() { height = chart.height, width = chart.width, chart.setSize(width, height, doAnimation = false); }); } } }]);
This issue happens because both series are not being drawn at the same moment. Second argument of the addPoint function is a flag that indicates whether the chart should be redrawn immediately after the addition or not. In your code 2 redraws happen instead of one. The update of the second series breaks the animation of the first one (it has no time to finish). The solution here is to redraw the chart only after the second call of addPoint(): series.addPoint([x, y], false, true); series2.addPoint([x, y2], true, true); Live demo: http://jsfiddle.net/kkulig/5y1dacxv/ API reference: https://api.highcharts.com/class-reference/Highcharts.Series#addPoint
Javascript,Highcharts : Avoiding parallel function calls
I am developing a dashboard, where there are 5 buttons, and on click of each button, corresponding chart is displayed in the same div. The structure of my code is as follows : $(document).ready(function(){ $("button").click(function(){ function requestData() { $.ajax({ url : ...., success : function(){ ..... //Real Time Plotting of Data chart.series[0].addPoint(eval(point), true, shift); setTimeout(requestData, 2000); } }); } chart = new Highcharts.Chart({ chart: { renderTo: 'chart', defaultSeriesType: 'spline' }, .... .... }); }); }); The Problem : On every click of the button, a parallel requestData() starts, multiple parallel threads run at the same time. This leads in random addPoint and increase in memory consumed. Also, when checked with Highcharts.Chart in the console, after every click, a undefined objects adds up. How do I restructure the code for optimum performance ?
Refer the code below, your high chart implement can be like this $(function () { $(document).ready(function () { $('#container').highcharts({ chart: { type: 'spline', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events: { load: function () { // set up the updating of the chart each second var series = this.series[0]; setInterval(function () { var x = (new Date()).getTime(), // current time y = Math.random(); series.addPoint([x, y], true, true); }, 1000); } } }, title: { text: 'Live random data' }, xAxis: { type: 'datetime', tickPixelInterval: 150 }, yAxis: { title: { text: 'Value' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { formatter: function () { return '<b>' + this.series.name + '</b><br/>' + Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 2); } }, legend: { enabled: false }, exporting: { enabled: false }, series: [{ name: 'Random data', data: (function () { // generate an array of random data var data = [], time = (new Date()).getTime(), i; for (i = -19; i <= 0; i += 1) { data.push({ x: time + i * 1000, y: Math.random() }); } return data; }()) }] }); }); }); Basically, you do not need to make your arrangement to live plotting, high chart has this option UPDATE Refer live fiddle http://jsfiddle.net/anilk/3u0ng35s/ Replace below data option to your ajax call data: (function () { // generate an array of random data var data = [], time = (new Date()).getTime(), i; for (i = -19; i <= 0; i += 1) { data.push({ x: time + i * 1000, y: Math.random() }); } return data; }
Highcharts not Drawing point on setInterval
I have data being put on an api every 30 seconds on a backend. On the frontend I am using highcharts to visualize the data and a setInterval setup to retrieve the new data every 30 seconds. My problem is that on that setInterval, the line graph disappears or does not draw to the next new dot. Does anyone now why this is? fiddle: http://jsfiddle.net/b8tf281n/3/ code: chart1 = { yAxisMin: 40, yAxisMax: 100 }; // empty objects for our data and to create chart seriesData = []; BPM = []; time1 = []; // console.log(chart1.data.series); $(function () { $(document).ready(function () { Highcharts.setOptions({ global: { useUTC: false } }); var url = 'http://msbandhealth.azurewebsites.net/odata/PulsesAPI/'; $.ajax({ url: url, dataType: 'json', context: seriesData, success: function (data) { // structure our data for (var i = 0; i < data.value.length; i++) { bpm = data.value[i].BPM; time = data.value[i].Time; BPM.push({ x: moment(time), y: bpm }); // console.log(BPM); time1.push(time); } console.log((new Date).getTime()); console.log(moment(time, "DD.MM.YYYY hh:mm:ss")); console.log(BPM); console.log(BPM[BPM.length - 1]); // console.log(seriesData); // set our data series and create new chart chart1.data.series[0].data = BPM; chart = new Highcharts.Chart(chart1.data); $('#container').css({ height: '400px' }); // console.log(sortedBPM); // console.log(time1); } }); // give highcharts something to render to var container = document.getElementById("container"); chart1.data = { chart: { renderTo: container, type: 'spline', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events: { load: function () { setInterval(function () { // find last data points var test = BPM[BPM.length - 1]; var x = (new Date).getTime(), y = test.y; console.log(x); shift = chart.series[0].data.length < 30; chart.series[0].addPoint([x, y], true, true); }, 30000); } } }, title: { text: 'Microsoft Band: Real Time Pulse Analysis' }, xAxis: { type: 'datetime', tickPixelInterval: 150, dateTimeLabelFormats: { }, }, yAxis: { min: chart1.yAxisMin, max: chart1.yAxisMax, title: { text: 'Heart Rate' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { formatter: function () { return '<b>' + this.series.name + '</b><br/>' + Highcharts.dateFormat('%H:%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 2); } }, legend: { enabled: false }, exporting: { enabled: false }, series: [{ name: 'Beats Per Minute', data: [] }] }; }); });
Your test.y is the problem. It returns undefined after one interval. Somehow BPM is changing in it's structure - changing each object from {x,y} to [0,1] - therefore I used: y = (test.y !== undefined)? test.y : test[1]; to either get the previous structure or the new. I also set the interval to 3 seconds for you to see the difference easier. Here's the DEMO.