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.
Related
I am currently using chart.js to plot spectral data from a EMI receiver. There are over 16000 (x,y) data indexes within each dataset and therefore I have made it so only the lines show without any points.
I now have a list of a few certain (x,y) value pairs that I would like to put points/markers on and add tooltips for. Is there a way to add tooltips and/or points or markers to only certain (x,y) value pairs within each dataset?
Any help would be appreciated. I will update with any photos/code if needed as I currently do not have an attempt at a solution for this.
EDIT1:
As you can see, it is very difficult to select the maximum point of the peaks due to how many data points make up the chart. I want to select only the local maximums and display tooltips for those points.
options.elements.point has a prop called radius. Radius can take either a number or an array of numbers. A single number will determine the radius for all of the points in your chart but the array will be able to determine each element's radius. This way you are able to selectively determine each point's radius with full control.
A solution for your example might look like this:
const options = {
elements: {
radius: allPoints.map(point => {
const maxPoint = Math.max(allPoints)
// return radius 0 for every point that is not the max and radius 1 (or bigger if needed) for the maximum point
return point == maxPoint ? 1 : 0
})
}
}
Following the c3js documentation there is no option for Bubble chart. One workaround for that is to setup scatter plot and specify point radius, but all of the bubbles will be the same height.
point = {
r: function(d) {
var num = d.value;
return num
},
Adding the value of axis inside the r solve the problem, but now the problem is how to setup very high or very low values ? For e.g if there is 1 000 000 value the whole chart will be colored. Is there any simple workarounds for that ?
First of all, set r to return the square root of your chosen variable e.g. return sqrt(num), that way a circle representing a data point 100 times the size of another has 100, not 10,000, times the area (area=pi r2 and all that)
If the numbers are still too big use a linear scale to restrict them to a usable size:
rscale = d3.scale.linear().domain([1,1000]).range([0,10])
and then return rscale(sqrt(num))
If your problem is to represent large and small values on the same chart so small values don't disappear and large values don't exceed the chart size look at using a d3 log scale:
rscale = d3.scale.log().base(10).domain([1,1000]).range([0,10])
Of course on a log scale the areas aren't linearly proportionate any more so whether the sqrt step is necessary is debatable. If you don't just remember to adjust the domain to account for this - change it to domain([1,1000000])
if you don't know the size of your numbers beforehand it will be worthwhile looping through your dataset to pick out the min and max to plug into the domain value: domain([your_min, your_max]). my examples above all assume a max of one million.
Here's an example I forked on jsfiddle, numbers from a few hundred to over a hundred thousand are displayed using a log scale and all are visible but the differences are still obvious:
http://jsfiddle.net/m9gcno5n/
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.
Is there any way of showing a 1:1 diagonal line in Highcharts? I am looking for a line which X and Y values always match.
I know how to render a line in Highcharts using the renderer, however, I don't want an independent line but one that reacts to the chart resizing/zooming. A series with [(0,0),(1,1)] is not really an option (it would affect zooming).
Something like this except x and y axis might vary their value due to zooming.
You can do it by detecting the setExtremes() event on you axes, and fire a function to get the axis extremes and draw a line.
(or, in this case, I used the afterSetExtremes() function)
In my example I did it by using a line series. I assume you can adapt it to use the renderer since you've already used the renderer to draw the line initially.
function redrawLine(chart) {
var xExt = chart.xAxis[0].getExtremes();
var yExt = chart.yAxis[0].getExtremes();
chart.series[1].setData([
{'x':xExt.min,'y':yExt.min},
{'x':xExt.max,'y':yExt.max}
]);
}
Example:
http://jsfiddle.net/jlbriggs/feLdzpux/
Of course, if your intent is to compare observed values to predicted values, then re-drawing the line when you zoom in is counter productive and misleading - the line should not move based on the zoom level - it should always be constant.
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
}
},