I'm experiencing some undesired behavior when using the built in data-grouping for Highstock charts. The result appears to be some sort of conflict between the underlying data-grouping logic (only grouping visible points?) and the extremes/navigator.
Some context:
I have a chart where the data points occur roughly every 2 minutes. Aside from viewing the point individually the user has the option to select a number of different groupings for the data points (15 minute intervals, hourly, and daily). The options for this are:
const dataGrouping = {
enabled: true,
forced: true,
approximation: 'sum',
units: [['minute', [15]]]
};
Where the units would be swapped out depending on which option was selected. This appears to be working as intended. Depending on which grouping the user has selected I now enforce restrictions on the navigator to snap to the nearest acceptable interval. For example, for the 15 minute interval:
const newMin = moment(extremes.min).minute(15 * Math.round(moment(extremes.min).startOf('minute').minute() / 15)).startOf('minute').valueOf();
let newMax = moment(extremes.max).minute(15 * Math.round(moment(extremes.max).startOf('minute').minute() / 15)).startOf('minute').valueOf() - 1000;
if (newMax > extremes.dataMax) {
newMax = extremes.dataMax;
}
if (newMin !== extremes.min || newMax !== extremes.max) {
this.chart.xAxis[0].setExtremes(newMin, newMax, true, true, { trigger: 'adjExtremes' });
}
This also appears to be working as expected with one small flaw: the right-most point on the graph trails off incorrectly. For instance, if the right-most point is at 3:00PM and meant to be an aggregation of the values between 3:00PM and 3:15PM the 3:00PM point will only sum any points between 3:00PM and 3:01PM as 3:01 - 3:15 are not technically visible on the graph (however the data is there, just not in the visible range).
Bad Right-Most Point
I've tried a number of different things to no avail. Subtracting a second off of the max extreme makes it so the point is no longer there, and therefore can't show an incorrect value on hover, however the line still trails off the to bottom. I believe that given the nature of the issue, no matter what I set the extreme to I will continue to have the problem. The Highstock demo example for Data Grouping doesn't appear to have this issue (points right on the line can be seen going up, even when the point/group isn't drawn on the graph).
My thought is that the correct solution to this would be to force Highstock to group points so long as the data exists, even if the points wouldn't technically be drawn on screen. I've tried turning off the various thresholds, but that also has no effect.
Related
I plot some series of data with Zingchart. The data is one entry per second, per set. The result is the following graph:
.
I am happy with this result. I get an overview of the plot that is very fast using "exact":false as plot attribute. Afterwards, I want to be able to 'zoom in' to see the detail:
And now I have too much detail. The attributes I have for plot are:
"maxNodes":2000,
"maxTrackers":2000,
I have been trying to play with those numbers but at the end, if I reduce the number I just have to zoom-in more. As I understand I get one node/tracker/information popup per data entry in the current status of the visualization only if there are less nodes than the limit defined.
Would it be possible to indicate Zingchart to place the nodes not in every data point, but with some kind of interval or intention?.
For example, in the second graph I would like to have nodes at the beginning / end and on the jump that the line makes. Or local maximums / minimums.
There are a few options.
1) You could change the "max-nodes" to a lower number. "max-nodes" just determines how many nodes are drawn while "max-trackers" determines how many you can interact with.
2) You could also add the following to your plot object...
marker: {
rules: [
{
rule: '%i%5 > 0',
visible: false
}
]
}
What that does it it checks the index (%i) of each marker. If the index of the marker modulo 5 is greater than 0, we don't display the marker (node). That means that all nodes except those evenly divisible by 5 will be hidden.
I'm on the ZingChart team. Let me know if this helps. Holla if you've got more questions.
I'm using Highstock (v4.2.3) to present data in a StockChart with a number of different Y axes, all plotted against time on the X axis. The data has gaps in it, and I'd like to depict those gaps, but when I turn on gapSize (with any value other than zero), there's a weird quirk that causes line rendering issues--when using the navigator to zoom in on certain date ranges (not all), in some cases (whose pattern I've yet to discern) the chart fails to fully render the line across the entire x axis.
This annotated screenshot depicts the issue.
When I turn gapSize off (or explicitly set it to zero), this problem goes away. Note that the gaps themselves appear correctly on the chart (when navigating to a date range that doesn't present the line rendering issue).
plotOptions: {
series: {gapSize:2}
}
Any ideas?
jsFiddle with your issue:
http://jsfiddle.net/2N52H/109/
As you can read in our API:
http://api.highcharts.com/highstock#plotOptions.line.gapSize
A gap size of 5 means that if the distance between two points is
greater than five times that of the two closest points, the graph will
be broken
As far as I know data you have has random gaps so you will never know what is the distance between two closest points. For example if you will have data in every one hour, distance between two closest points will be 15 minutes and your gapSize will be set to 2, you will see only your closest points.
When you are using zoom sometimes your visible data closest distance is changing so the gaps are changing as well.
See this example:
http://jsfiddle.net/2N52H/111/
Maybe you can use xAxis.ordinal parameter to visualise your gaps:
http://api.highcharts.com/highstock#xAxis.ordinal
You can also change standard functionallity by using wrapper. Here you can read about it:
http://www.highcharts.com/docs/extending-highcharts/extending-highcharts
For example you can change gappedPath function:
(function(H) {
H.wrap(H.Series.prototype, 'gappedPath', function(proceed) {
var gapSize = this.options.gapSize,
xAxis = this.xAxis,
points = this.points.slice(),
i = points.length - 1;
if (gapSize && i > 0) { // #5008
// extension for ordinal breaks
while (i--) {
if (points[i + 1].x - points[i].x > gapSize) {
points.splice( // insert after this one
i + 1,
0, {
isNull: true
}
);
}
}
}
return this.getGraphPath(points);
})
}(Highcharts))
example:
http://jsfiddle.net/2N52H/113/
Kind regards.
By default scale of x axis is calculated from values. This gives uneven distance between two adjasted points. Like for example if I have an array of values like [1,2,5], there will be different distance on x axis for point, and also x axis labels will contain some other values, like 1,2,3,4,5. In case on dates displayed on x axis there may be cases when two equal dates are printed, looks ugly.
Take a look at this plunker. If you maximize your browser window, you could see that x axis labels have duplicates (like 02/09/2015 is visible 2 times on my screen). Also the distance between point is different.
How can I:
Make so that no duplicate x axis labes are present?
Distance between points is equaly distributed based in graph's width (not scaled based on values)?
You can explicitly set tickValues() and specify what ticks you want to show.
Alternatively, ticks() is more flexible, but gives you less control.
(Search for "D3 duplicate dates". This one may be helpful for example).
The reason the dates are repeating is that they are in fact different (equally spaced) timestamps that occur on the same day, since the spacing is < 24 hours. If you want to label with distinct dates, you could select a specific time on each day for the tick to fall on.
I'm using Highcharts for a project in which I have to display two series with about a thousand points each. The x-axis represents a date, and the y-axis a quantity. In addition, each point has an associated list of namesMy data is day-by-day without gaps, with a structure such as
var mydata = [ ...
{x: theDate, y: theValue, names: theNames},
... ]
where theNames is an array of strings. I can access these in the tooltip formatter through this.points.point.names, given that the range displayed on the chart is small enough. If I change the x-axes so that the start date and end date are more than roughly a year apart, then the tooltip is not rendered at all.
One of the possible avenues that I have tried but failed with so far is setting the turboThreshold limit to the length of the longest series plus 1. Setting this lets me at least display a graph when mydata.length > 1000 (the default value). However, this only displays the tooltip if the x-axis range is less than 261. Otherwise, the tooltip disappears entirely, as does the point.data object where I'm getting the name from.
I'm also not great at JavaScript, but I was wondering if there were a way to separate the names of the points from the array containing them (in my examples, myData1 and myData2) and somehow access those names from the tooltip function without going through the current point.
Here is the link to the jsFiddle demonstrating this issue.
All help is appreciated!
The problem is in dataGrouping, when disabled works fine: http://jsfiddle.net/34tfg/1/
DataGrouping is method in Highcharts to approximate points and display them when width of the chart is not enough, e.g. how to display 10 000points in a chart of width 1 000px -> 10 points in a one pixel..? And when dataGrouping is used, new points are created, so all your custom options like 'names' etc. are lost (at least not accessible).
Code:
plotOptions: {
line: {
dataGrouping: {
enabled: false
},
turboThreshold: 10000
}
},
I have a dynamic data array that contains 3 ints that are used to build a pie chart. In most cases it works fine IE: [5, 10, 3]. The pie chart renders correctly and you see all the pieces.
However in some cases the numbers can be widely different. IE [1,500,250] or [400,1,2]. When this is the case you will only see the larger of the pie pieces and the smaller ones become so small they can not be seen; or clicked.
I need some way of correcting the data array for these cases. I have the ability to retain the true value while adjusting the display value so the pieces show up. What I am looking for is a check to see if it's necessary and then a relative number to adjust it by based on the other values.
Suggestions?
Well firstly I'd say you aren't so much "correcting" the data as fudging the data to meet your requirements.
Basically, there is a minimum percentage for which a slice of that proportion will be clickable and you will need to bring all pieces up to at least this size.
Of course - this can't work at the most extreme examples. If you had 1,000,000 slices all of the same value then no matter how you scaled them, some of them are going to be too small (or all of them).
You also need to be aware of how scaling certain very small slices will throw out the apparent proportions between other, larger, slices.
But - a very crude way of doing it could be something like...
var minPC = 0.5 , // the minimum %age slice visible
total; // total should be set to the sum of the values of all your slices
var minValue = total / 100 * minPC; // The smallest value visible (given the current total)
for (var slice in slices) { //assuming slices is a standard JS 'array'
if ( slices[slice] < minValue ) slices[slice] = minValue;
}
of course making the slices bigger like this will in turn increase the total - meaning that the small slices will still be less than the minimum visible percentage. You will need to make minPC sufficiently large to cope with this. And of course the more very small slices you have the worse this effect will be. You could account for this be re-scaling the larger slices.
However - I would advise you find a better way of the user interacting with the data by letting them select on/off slices - or by having slices 'explode'.
You seem to want to resize the segments of the pie if they are too small to make them visible/clickable.
May I suggest that instead of solving the problem this way (which would give an invalid
representation of the data), you could instead use labels outside of the pie chart to point at the segments? These labels could then, themselves, be made clickable.
The sum of the values in your array represent the entire "size" of the pie. The percentage of the pie each value has is the visual weight of that piece. You probably want to set a minimum threshold for the percentage size of each piece (the minimum threshold would be related to the diameter of your chart).
ie. [500, 490, 10] -> [500/1000, 490/1000, 10/1000] -> [50%, 49%, 1%]
If any value is less than your minimum threshold, you need to increase it to the minimum threshold and adjust your other values accordingly, so they all add up to 100%
It is related with fact that all points are sum and each value is calculated to pixels.