I've got a chart that has a large number of data points. I'm setting the extremes right now so it only shows a smaller number - about 100 or so at a time. The issue I have is I don't want to disable the range selector or the manual input for dates, but currently the user can expand the range selector to include the entire data set. Is there any way to limit this so they can only grab, at most, X number of points?
I don't want to use data grouping either, I have different data for different data groups, so it's important the grouping does not change. Thanks in advance for any pointers on this one!
Unfortunately you can't disable range selector for such purpose, but you can overwrite extremes after user change them, see:
api.highcharts.com/highstock#xAxis.events.afterSetExtremes So for example, if user takes range for 4 days and you want max for 2 days - grab one of min or max, and add/remove two days in extremes (call chart.xAxis.setExtremes() with new extremes). Of course, it will call another afterSetExtremes, so it would be infinite loop, however now extremes will be proper (two days), so it wouldn't call another setExtremes().
Here's a working example of using afterSetExtremes (like Dexter describes) to create a maximum range from the range selector :
http://jsfiddle.net/B7vCR/3/
xAxis: {
minRange:6 * 30 * 24 * 3600 * 1000,
events: {
afterSetExtremes: function(e) {
var maxDistance = 10 * 30 * 24 * 3600 * 1000; //8 months time
var xaxis = this;
if ((e.max - e.min) > maxDistance) {
var min = e.max - maxDistance;
var max = e.max;
window.setTimeout(function() {
xaxis.setExtremes(min, max);
}, 1);
}
}
}
}
From this post
http://forum.highcharts.com/viewtopic.php?f=12&t=21741
Related
I'm wondering if it's possible to define a custom ordering or format for the xAxis in highcharts. My dataset has a date time which would be used for the xAxis however my client has specified that it should show the 'Period' on the xAxis. A period is specified as a 30 minute slice - meaning there are 48 periods in a day.
The range of the data is from a period on the previous day to the current day with that period. For example 06/03/2017 Period 11 (10:00) to 07/03/2017 Period 11, the xAxis should look like so:
Currently I've attempted to do this by fiddling with the actual dateTime of each point, so that it is set to Y-m-d H:i:{Period} and then using the dateFormat to only show seconds on the xAxis. However this leaves a gap in data between 2017-03-06 23:59:{Period 48} and 2017-03-07 00:00:{Period 11}
Assuming your series-data is arranged as pairs of [<timestamp in milliseconds>, <value>] you can leave your data alone and simple do calculations and presentation of the label.
To show the labels as we want we use xAxis.labels.formatter (and possibly tickInterval to space them as we want). For example:
xAxis: {
type: 'datetime',
labels: {
formatter: function() {
return createLabelFromTimestamp(this.value);
}
},
tickInterval: 1800000
}
The calculation of the period number (as described in question) can be done for example like this:
function createLabelFromTimestamp(timestamp) {
var hms = timestamp % (1800000 * 48);
var period = hms / 1800000;
// if 0-th period, show date instead
if(period == 0) {
var date = new Date(timestamp);
return date.toDateString();
}
// otherwise show period number
else {
return period;
}
}
We simply modulo away the day and divide to find what 30-minute segment we are in.
See this JSFiddle example of it in action.
I used configured Highstock's "tickPositioner" to set ticks dynamically for different ranges of data. For example, if the range is 1 hour max => 1 tick every 10 minutes. Here is some code of the function I put in tickPositioner (which is in xAxis config):
if (xDataRange <= oneHour) {
// If range is 1 hour max => 1 tick every 10 minutes
increment = oneMinute*10;
positions.info.unitName = "minute";
} else if (xDataRange > oneHour && xDataRange <= oneDay) {
// If range is between 1 hour and 1 day => 1 tick every hour
increment = oneHour;
positions.info.unitName = "hour";
} else { ... }
Here is an illustrating fiddle : http://jsfiddle.net/E6GHC/124/
(I know that the range choices are not the best here.)
The QUESTION: I would like to do the same with the minorTicks.
As you can see in the Fiddle, when you click on the month button the ticks are positionned each week and minorTicks are each day. But this is static configuration (minorTickInterval: oneDay).
I have some ideas and I have tried them and nothing seems to work out..
So if someone have any suggestion ? I would be veryyy thankful.
The perfect thing would have been to be have to set/update the minorTickInterval in tickPositioner function.
I have a dynamic data series like this
[1,0],[2,0],[3,0],[4,0],[5,0],[6,2],[7,5],[8,6],[9,6],[10,6],[11,7],[12,8],[13,8],[14,9]
The data grows automatically, so later on, an extra data point will be added e.g. [15,13]
I have an input field in which the user can select how many points from the end he wants to show.
For example if he inputs 5, only [10,6],[11,7],[12,8],[13,8],[14,9] should be visible. But when the additional point is added, this should become [11,7],[12,8],[13,8],[14,9],[15,13] automatically.
I think I have to use chart.xAxis[0].setExtremes() but I don't know what to enter as parameters... ?
You will have to "reapply" setExtremes when adding a point. The setExtremes function takes in these parameters (API):
setExtremes (Number min, Number max, [Boolean redraw], [Mixed animation])
You would have to use min and max to show the desired number of points, and have that include the last one. For example, you could do something like this:
var chart = $('#container').highcharts();
var numberOfPointsToShow = 5;
// Add new random point
chart.series[0].addPoint(Math.random() * 25);
// Get index of last point
var lastPoint = chart.series[0].data.length - 1;
// Set extremes to go from "min" (based on last point) to last point
chart.xAxis[0].setExtremes(
lastPoint - (numberOfPointsToShow - 1), // min
lastPoint); // max
See this JSFiddle example with dynamic adding of points.
Is there a way to get only three steps on the xAxis, one at start, one in the middle and one in the end. I've played around with xAxis.labels.steps but I couldn't get an reliable result.
Note the xAxis type is datetime.
There is at least three ways to achieve that (which are automatically):
Use tickPositioner (the best IMHO): you have full access to decide where tick should be set (for example: [min, average, max]).
Use tickPixelInterval: useful only when you have fixed width of the chart, and when interval will be multiple of ncie numbers (like 0 - 1 - 2, or 100 - 200 - 300)
Use tickInterval: useful only when you know range of xAxis, for example 0-10, so you can set tickInterval: 5
And jsfFiddle with compare: http://jsfiddle.net/FQ68Y/3/
You can do this with the tickPositions option or the tickPositioner function:
http://api.highcharts.com/highcharts#xAxis.tickPositioner
tickPositions: [0, 1, 2]
or something like:
tickPositioner: function () {
var positions = [],
tick = Math.floor(this.dataMin),
increment = Math.ceil((this.dataMax - this.dataMin) / 2);
for (; tick - increment <= this.dataMax; tick += increment) {
positions.push(tick);
}
return positions;
}
As the other answers mention there is the tickPositioner field. For some reason it dont work out of the box. I had to add an info property to the returning array to get the xAxis to display formatted dates instead of just the milliseconds, as found in this fiddle.
tickPositioner: function (min, max) {
var ticks = [min, min + (max - min) / 2, max];
ticks.info = {
unitName: 'hour',
higherRanks: {}
};
return ticks;
}
I have a chart with multiple series for which I have a button that resets the yAxis to a specific amount. I would like to set this specific amount to be the 85th percentile of the yAxis values. Is there a way to calculate this?
jsfiddle example: http://jsfiddle.net/inadcod/TynwP/
Very strange that you wish to do this on the client, you could very easily sort and get the value of the 85th percentile on the server where you are actually sending the data from and use it as a max value for the y axis.
Anyway, you can access the data values using the series.points object array, this contains all the points for the given series, it has many properties of which point.y seems to be of your interest. Loop through all these and store them in another array for convenience and sort this new array. take the length of the array and multiple by the factor you wish to (0.85) and this is the index of the element a.k.a. 85th percentile. Set the min of the given yAxis using this value
var yData = [];
$.each(chart.series[0].points, function() {
yData.push(this.y);
});
var sortedY = sort(yData);
var eightyFifthPercentile = sortedY[Math.floor(sortedY.length * 0.85)];
alert(eightyFifthPercentile);
http://jsfiddle.net/jugal/HkS2Y/
You can do it this way:
var yAxis = chart.yAxis[0];
var extremes = yAxis.getExtremes();
yAxis.setExtremes(extremes.min, extremes.dataMax * 0.85);
See demo here: http://jsfiddle.net/gyavJ/