How do i set setInterval in angularjs highcharts ng line chart config settings. I am working on creating a dynamic line chart using highcharts-ng and my chart displays the initial static data and when it comes to displaying dynamic data i see that load event in scope.chartConfig4 does not get attention so my chart remains static. Here is my code snippet.
Update: I am using highcharts-ng an angular directive which does not display my dynamic map even after i corrected the timeout to interval. I am trying to convert the following code http://www.tutorialspoint.com/highcharts/highcharts_dynamic_spline.htm using angularjs . Please help.
$scope.chartConfig4 = {
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: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Users(in thousands)'
},
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: 'Users',
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;
}())
}]
};
Update: I am using highcharts-ng an angular directive which does not display my dynamic map even after i corrected the timeout to interval. I am trying to convert the following code http://www.tutorialspoint.com/highcharts/highcharts_dynamic_spline.htm using angularjs . Please help.
setInterval takes you outside of Angular's scope, meaning that $scope.apply() is never called. You should use $interval instead so that a digest cycle is properly triggered.
$interval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], true, true);
}, 1000);
Related
So, What I have is a condition in a MySQL to show the first 1000 data points first and then the other 2000 datapoints after that in Highcharts.
if lastindex==0:
cur.execute("SELECT data,value FROM table where id<1001")
else:
cur.execute("SELECT data,value FROM table where id>1001 and id<3000")
data = cur.fetchall()
//python Code to fetch SQL data
Now what I am doing is that I am rendering that data into the Highcharts, the data is being rendered. but the problem arises that after showing the first 1000 data points, the Highcharts value starts from 0 and then shows the other 2000 points
the data is not displaying continuously as it should plot the send array data just after the end of the first data.
I think the Highcharts is being called Twice, What can I do to append the 2nd set of data to the first set without reloading the whole chart.
Here's a snip of my Highchart's js
Highcharts.chart("chartcontainer", {
chart: {
type: 'line',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
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;
}())
}]
});
What I want is just to append the event data rather than loading the whole chart.
How can I reload a particular Highchart value without reloading the whole chart ?
What do you think about updating the current series with new data, which will be an array of old data merged with the new one?
chart: {
events: {
load(){
let chart = this,
currentSeries = chart.series[0],
newData;
newData = [...currentSeries.userOptions.data, ...data1]
setTimeout(()=> {
chart.series[0].update({
data: newData
})
}, 5000)
}
}
},
See the demo
We are running into an issue where our scatter chart starts to act abnormally when we reach 5,000 points on the screen. Specifically, at 5k+ points, the point event 'click' will stop firing when we click on a point, and our point formatting (fillColor & symbol) is lost.
4999 points: http://jsfiddle.net/xrpf0pfq/7/
$(function() {
// Prepare the data
var data = [],
n = 4999, // < 5K points
i;
for (i = 0; i < n; i += 1) {
data.push([
Math.pow(Math.random(), 2) * 100,
Math.pow(Math.random(), 2) * 100
]);
}
if (!Highcharts.Series.prototype.renderCanvas) {
console.error('Module not loaded');
return;
}
console.time('scatter');
console.time('asyncRender');
$('#container').highcharts({
chart: {
zoomType: 'xy'
},
xAxis: {
min: 0,
max: 100,
gridLineWidth: 1
},
yAxis: {
// Renders faster when we don't have to compute min and max
min: 0,
max: 100,
minPadding: 0,
maxPadding: 0
},
title: {
text: 'Scatter chart with ' + Highcharts.numberFormat(data.length, 0, ' ') + ' points'
},
legend: {
enabled: false
},
series: [{
type: 'scatter',
data: data,
marker: {
radius: 5,
symbol: 'triangle', //shows correctly
fillColor: 'rgba(128,0,128,1)' //shows correctly
},
point: {
events: {
click: function() {
alert("click"); //event is fired correctly
}
}
},
tooltip: {
enable: false,
followPointer: false,
pointFormat: '[{point.x:.1f}, {point.y:.1f}]'
},
events: {
renderedCanvas: function() {
console.timeEnd('asyncRender');
}
}
}]
});
console.timeEnd('scatter');
});
5000 points: http://jsfiddle.net/xrpf0pfq/10/
$(function() {
// Prepare the data
var data = [],
n = 5000, // 5K points
i;
for (i = 0; i < n; i += 1) {
data.push([
Math.pow(Math.random(), 2) * 100,
Math.pow(Math.random(), 2) * 100
]);
}
if (!Highcharts.Series.prototype.renderCanvas) {
console.error('Module not loaded');
return;
}
console.time('scatter');
console.time('asyncRender');
$('#container').highcharts({
chart: {
zoomType: 'xy'
},
xAxis: {
min: 0,
max: 100,
gridLineWidth: 1
},
yAxis: {
// Renders faster when we don't have to compute min and max
min: 0,
max: 100,
minPadding: 0,
maxPadding: 0
},
title: {
text: 'Scatter chart with ' + Highcharts.numberFormat(data.length, 0, ' ') + ' points'
},
legend: {
enabled: false
},
series: [{
type: 'scatter',
data: data,
marker: {
radius: 5,
symbol: 'triangle', //marker shape not showing
fillColor: 'rgba(128,0,128,1)' //color not showing
},
point: {
events: {
click: function() {
alert("click"); //click even not firing
}
}
},
tooltip: {
enable: false,
followPointer: false,
pointFormat: '[{point.x:.1f}, {point.y:.1f}]'
},
events: {
renderedCanvas: function() {
console.timeEnd('asyncRender');
}
}
}]
});
console.timeEnd('scatter');
});
Is there way to keep the marker formatting and make the click event fire when you have 5K or more points on a scatter plot?
Apparently, this behaviour is caused by boost module. Look at the example without it: http://jsfiddle.net/xrpf0pfq/12/. You can check in a source code of a boost module (http://code.highcharts.com/modules/boost.src.js) that the boostThreshold property is set with value 5000. You can set boostThreshold by yourself, check out the example: http://jsfiddle.net/xrpf0pfq/16/.
plotOptions: {
series: {
boostThreshold: 8001
}
}
Also, not working click event with boost module is a known issue (beside, it is not good idea to click on a point where there are thousands of them and they are densely populated). There is a workaround for that though, take a look at this topic on GitHub: https://github.com/highcharts/highcharts/issues/4569. As Paweł mentioned, to make click event work with a huge amount of points, you need to enable halo and make it clickable (here is an example with boost module loaded and with more points than boostThreshold value but with click event working: http://jsfiddle.net/xrpf0pfq/17/).
mouseOver: function() {
if (this.series.halo) {
this.series.halo.attr({'class': 'highcharts-tracker'}).toFront();
}
}
Regards.
Ran accross the same problem. The halo-workaround didn't work for me, because i wanted to get the click event for the recently highlighted point, even if it is not directly clicked. Highcharts has the ability to highlight the nearest point if you point anywhere on the chart. My workaround is, to use the tooltip formatter to store the x value away and then use it on the global click event for the chart.
See the fiddle:
http://jsfiddle.net/StefanJelner/a1m0wuy6/
var recent = false;
$('#container').highcharts({
chart: {
events: {
click: function() {
console.log('chart click', recent);
}
}
},
tooltip: {
formatter: function() {
recent = this.x;
return 'The value for <b>' + this.x +
'</b> is <b>' + this.y + '</b>';
}
},
plotOptions: {
series: {
point: {
events: {
click: function (e) {
console.log('point click', e); // never happens
}
}
}
}
}
});
This should also work for Version 6.
I have a ASP.NET MVC project with SignalR.
I have a page with a HighChart and the script looks like this:
$(function () {
window.Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$(document).ready(function () {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
marginRight: 10
},
title: {
text: 'GMAS Queues'
},
xAxis: {
type: 'datetime',
tickInterval: 500,
labels: {
enabled: false
}
},
yAxis: {
title: {
text: 'Queue Count'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Processing Queues'
}]
});
});
$.connection.hub.logging = true;
// Reference the auto-generated proxy for the hub.
var chartData = $.connection.processingQueuesHub;
// Create a function that the hub can call back to display messages.
chartData.client.updateQueueCounts = function (data) {
//$.each(data, function(i, item) {
// // Add the message to the page.
// $('#chartDataLog').append('<li><strong>' + htmlEncode(item.QueueName)
// + '</strong>: ' + htmlEncode(item.Length) + '</li>');
//});
// set up the updating of the chart.
var series = chart.series[0];
$.each(data, function (i, item) {
if (item.QueueName == "Queue A") {
var x = Date.parse(item.Date),
y = item.Length;
series.addPoint([x, y], true, false);
}
});
};
However, I see the graph but not the points.
The strange part is the series data points are there:
Anyone know why HighCharts is not rendering the points?
Thanks, Bill N
I have to thank my good friend and co developer for figuring this out. He is a smarter and braver man than me. :) He went to the highcharts source and found that the highcharts breaks if you add to the graph series before the initial animation is completed. The animation is why the clip-rect is zero-width (it animates from zero to full width over 1s when you first create the chart). You end up adding a point to the series before this animation even really starts. This kills the animation but it doesn’t fix the width of the clip-rect. The fix is to add animation is false for the series.
series: [{ name: 'Processing Queues', data: [], animation: false }]
It looks like you are not defining what your chart.series is until it is created. The line in your ajax is as follows and its not waiting for DOM ready:
var series = chart.series[0];
But you do not define chart until $(document).ready(function () {.... Try keeping your chart object in scope of your ajax.
I have a requirement to plot run history of a task in Highcharts. It needs to show that run history of the tasks as a horizontal bar. There are additional requirements which I've added as an update below. Recently I found out that inverted option is not supported in StockChart and that only navigator & rangeSelector are available in StockChart. Therefore I am using those functions.
So in order to achieve the requirement I created something similar to this jsfiddle example (found somewhere while browsing don't remember the source) and ended up with this plunker link with help from my previous question, thanks to Pawel Fus
Updating question to avoid confusion
Additional requirements:
Show only those tasks which ran in a particular date and time range. In case there are too many runs, such as more than 10 run, then there needs to be a way to display only 10 tasks visibly with a y-axis that is scrollable to show other tasks.
plunker link to the problem
Problem explanation of above plunker.
If you check the screenshot below from above plunker, the time range is from 12/12/2014 09:32:26 to 12/12/2014 10:32:26 and there are only 2 tasks that has run m_ARRAYV_SALES_ZIG1_CALL2_VOD__C_OB & m_ZIG2_HCP_MERGE_IB_CN. However I can see another task in between LILLY_C which did not even ran in this date time range. (In actual data there are more than 10 tasks that clutters this chart which does not even fall under this date time range)
Also if you notice at the bottom most right corner time shifted from 09:38 to 19:20. 19:20 is the end time for m_ZIG2_HCP_MERGE_IB_CN task.
Below is my chart options
var chart_options = {
chart: {
renderTo: 'container',
height: 600
},
title: {
},
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
gridLineWidth: 1,
tickInterval: 1 * 3600 * 1000,
dateTimeLabelFormats: {
month: '%b %e, %Y'
}
},
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
formatter: function() {
if (tasks[this.value]) {
return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Task'
}
},
rangeSelector: {
selected: 0,
buttons: [ {
type: "minute",
count: 60,
text: "1h"
}, {
type: "minute",
count: 180,
text: "3h"
}, {
type: "minute",
count: 300,
text: "5h"
}],
inputDateFormat: '%m/%d/%Y %H:%M:%S',
inputEditDateFormat: '%m/%d/%Y %H:%M:%S',
inputBoxWidth: 120
},
navigator: {
enabled: false
},
legend: {
enabled: false
},
tooltip: {
shared: false,
formatter: function() {
var str = '';
str += 'Task: ' + this.series.name + '<br>';
str += 'From: ' + Highcharts.dateFormat('%m/%d/%y %H:%M', this.point.from) + '<br>';
str += 'To: ' + Highcharts.dateFormat('%m/%d/%y %H:%M', this.point.to) + '<br>';
return str;
}
},
plotOptions: {
line: {
lineWidth: 10,
marker: {
enabled: true
},
dataLabels: {
enabled: true,
align: 'left',
formatter: function() {
return this.point.options && this.point.options.label;
}
},
states:{
hover:{
lineWidth:10
}
}
},
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
var query = '{ "task_id": "'+this.task_id+'","start_time": '+this.from+',"exclude_interval": '+opExcludeMinutes+',"size": 10 }';
$scope.taskName = this.series.name;
$scope.isTaskSelected = false;
$scope.operationalReportAgentTaskHistoryServiceRequest(query);
}
}
}
}
},
series: seriesData
};
So after a few hours of digging, I have just found out the culprit (or I really hope so). The problem is your definition of yAxis label formatter:
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
formatter: function() { // THIS IS THE PROBLEM
if (tasks[this.value]) {
return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Task'
}
},
You don't actually check if you should display the label according to task.intervals (see json.js). A simple update (Plunker) of the formatter seems to work:
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
formatter: function () {
console.log("scripts.js - yAxis.labels.formatter", this.value);
if (tasks[this.value]) {
//if (tasks[this.value].name === 'LILLY_C') {
var _xAxis = this.chart.axes[0];
var _task = tasks[this.value];
var _show = false;
// Not optimized for large collections
for (var _i = 0; _i < _task.intervals.length; _i++) {
var _int = _task.intervals[_i];
if (_xAxis.min <= _int.to) {
_show = true;
}
}
console.log("scripts.js - yAxis.labels.formatter",
tasks[this.value].name,
_show,
_xAxis.min,
_xAxis.max,
_task.intervals
);
if (_show) {
return tasks[this.value].name;
} else {
return;
}
//}
//return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Task'
}
},
See Plunker for demo.
Meaning of the yAxis labels is: Show label if you see a run in the graph or if there is a run on the right of the graph. Please modify the condition
if (_xAxis.min <= _int.to) {
as you see fit.
Disclaimer: I don't use Highcharts, so this answer tries to explain the problem and not to suggest a Highcharts-way of solving the problem.
Lessons learned:
yaxis-plugin.js is irrelevant to the problem.
Highstock.js is an open-source library (highstock.src.js). Any debugging is much easier if you debug original source code. Minified code adds unnecessary complexity and guessing. I have downloaded the library and added some console.log() to find out what is going on.
I've been working on this for hours and couldnt figure it out, I'd appreciate if anyone could help.
$(function() {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
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: {
max: 400,
min: 0,
plotLines: [{
value: 200,
width: 1,
color: '#ccc',
}]
},
tooltip: {
enabled: false
},
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++) {
data.push({
x: time + i * 1000,
y: time + 4 * 50
});
}
return data;
})()}]
});
});
});
Here's what I'm trying to do:
Instead of current time on the xAxis, I like to start from 00:00 and run 5 seconds increments.
I would also like to have the Y value to have random numbers, not sure why it is not working
Last, I would like to get value from another element, and draw a horizontal line on the graph accordingly.
Thanks for looking...
1 - Keep a running counter of the seconds (i) and use setHours() to set the hours,minutes,seconds and milliseconds...the only one you'll really care about is seconds though.
var i = 0;
setInterval(function() {
var x = (new Date((new Date()).setHours(0,0,i,0)).getTime()),
y = Math.random()*400;
series.addPoint([x, y], true, true);
i++;
}, 1000);
2 - Multiply your Math.random() by something (like your max y value).
Math.random():
Returns a floating-point, pseudo-random number in the range [0, 1)
that is, from 0 (inclusive) up to but not including 1 (exclusive),
which you can then scale to your desired range.
3 - Slightly unclear on what you're looking for, would you mind specifying?
EXAMPLE