Attempting to create a second level of data in the xrange charttype of highcharts does not behave as expected
see jsfiddle https://jsfiddle.net/bo8eL42v/10/ and highcharts documentation https://api.highcharts.com/highcharts/series.xrange.data.drilldown
BACKGROUND - IDEAL BEHAVIOR:
upon clicking on a series the chart is redrawn w/ that same series broken down into time buckets (Day || Week) as the categories
-- this would allow for a Day over Day / Week over Week comparison rather than a Person by Person comparison
SubPar Alternate solution is to use the series.events.click to trigger a func that would overwrite the chart entirely w/ the DayOverDay behavior
Implemented a basic jsfiddle to test that conceptually drilldown should work as described
...
x: Date.UTC(2014, 11, 10),
x2: Date.UTC(2014, 11, 23),
y: 2,
drilldown: 'a'
}],
...
}],
drilldown: {
series: [{
id: 'a',
data: [{
x: Date.UTC(2014, 10, 21),
x2: Date.UTC(2014, 11, 1),
y: 0,
partialFill: 0.25
},{
x: Date.UTC(2014, 11, 1),
x2: Date.UTC(2014, 11, 2),
y: 0,
partialFill: 0.25
}]
}]
}
Expected: clicking on any of the datapoints where drilldown: 'a' should redraw the chart w/ only the points defined in the drilldown.series.'a' where 'a' is the id
Actual: nothing happens, no errors thrown
You need to include the drilldown module for the drilldown to function:
<script src="https://code.highcharts.com/modules/drilldown.js"></script>
See this JSFiddle demonstration.
Related
I'm exploring Highcharts and it seems like a very comprehensive package! I have a question regarding legend colors.
I notice that when I use a linear color gradient for a line, the color next to the legend (I believe it's called the symbolColor) may or may not show up, depending on the format I use:
1) symbolColor works fine: linearGradient: [ 00, 00, 00, 350 ]
2) symbolColor doesn't show up: linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }
I'd rather use the second format; it's easier and the first is not responsive.
Should the symbolColor always show up and this is an obscure issue/bug? Or am I doing something wrong? I also just noticed that if the marker is enabled in the plotOptions for series, symbolColor works fine with the second format. But I have many data points and don't want to use markers.
The fiddle graph has two lines -- purple and green -- and while the purple symbolColor using method (1) looks fine, you'll notice that the green symbolColor using method (2) doesn't show up.
https://jsfiddle.net/jwinkle/s6d9ah17/6/
In your HTML file, add:
<script src="https://code.highcharts.com/maps/modules/map.src.js"></script>
Above your chart code add:
Highcharts.addEvent(Highcharts.Chart.prototype, 'render', function() {
this.series.forEach(function(series) {
if (series.legendLine) {
var pathDef = series.legendLine.attr('d').split(' ');
pathDef[5] = parseFloat(pathDef[2]) + 0.0001;
series.legendLine.attr({
d: pathDef
});
}
})
});
The fix is in adding a smidge to your path definition (you can test this by going into the svg path element in dev tools and changing the last number in the 'd' attribute to a float:
<path fill="none" d="M 0 11 L 16 11" ... ></path>
becomes:
<path fill="none" d="M 0 11 L 16 11.1" ... ></path>
The function above goes through each series and massages the line data adding the fractional value in the right place. Total hack. However why the line does not appear if it does have this fractional value, I don't know. I would also test this across browsers to see that it works consistently as it may not (I tested in Chrome).
Here is a somewhat related issue where I cribbed the fix: https://www.highcharts.com/forum/viewtopic.php?t=38588
(Most of it is addressing a completely different problem, but the legend lines did show up so I investigated why).
If you don't want to use the extra library, you could probably write a native js function to find the legend lines and manipulate them in the same way.
Here, you can find a nice explanation of the problem.
The difference results from the fact that Highcharts uses 'userSpaceOnUse' as a default value for gradientUnits if a gradient is defined as an array.
Highcharts source code:
// Keep < 2.2 kompatibility
if (isArray(gradAttr)) {
(colorOptions as any)[gradName] = gradAttr = {
x1: gradAttr[0] as number,
y1: gradAttr[1] as number,
x2: gradAttr[2] as number,
y2: gradAttr[3] as number,
gradientUnits: 'userSpaceOnUse'
};
}
As a possible solution, you can set gradientUnits also for linearGradient defined as an object:
color: {
linearGradient: {
...,
gradientUnits: 'userSpaceOnUse'
},
...
}
Live demo: http://jsfiddle.net/BlackLabel/yz6sagxj/
Or modify the paths very slightly so that they are not perfectly horizontal
chart: {
events: {
render: function() {
this.series.forEach(function(series) {
if (series.legendLine) {
var pathDef = series.legendLine.attr('d').split(' ');
pathDef[5] = parseFloat(pathDef[2]) + 0.0001;
series.legendLine.attr({
d: pathDef
});
}
})
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/L1kzg0cn/
Github thread: https://github.com/highcharts/highcharts/issues/1936
In addition to #Katharine's solution, here's another I discovered.
If I enable the marker in one series (setting the radius to 0) and then put the data in a second series which is linked to the previous, it works. (If I do it all in one series, there is again no legend color.)
series: [{
name: 'purple', lineWidth: 3, color: {
linearGradient: [ 00, 00, 00, 350 ],
//linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1, },
stops: [
[0, 'purple'], // start
[1, 'black'] // end
],
},
data: [ 100, 95, 80, 60, 35, 50, 20, 10, 3, 2, 30, 40, ],
},{
marker: {
enabled: true,
radius: 0,
},
name: 'green', color: 'green', lineWidth: 3,
},{
linkedTo: ':previous',
lineWidth: 3, color: {
//linearGradient: [ 00, 00, 00, 350 ],
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1, },
stops: [
[0, 'green'], // start
[1, 'black'] // end
],
},
data: [ 100, 100, 95, 80, 60, 35, 50, 20, 10, 3, 2, 30, ],
}],
Here's the "fixed" fiddle: https://jsfiddle.net/jwinkle/wztq78n1/6/
I reported the original issue as a possible bug to Highcharts, and they confirmed that it's an SVG rendering problem out of their control.
This is my chart
I need that tick start from the start of my chart, without padding left.
I tried read docs, but I couldn't find anything about it
Per the docs it should be doing this anyway with xAxis.startOnTick:
Whether to force the axis to start on a tick.
Use this option with the minPadding option to control the axis start.
Defaults to false.
So, perhaps you overwrote this in your chart code?
Update:
So, from your code what you have is a categorical xAxis and an area line chart. Stylistically* this does not make much sense as the entire category "bin" is one single value and you are putting in time values (I assume since they are ['00:00', '05:00', '05:00', '05:00', '05:00']). Why not make an actual time series xAxis? This would give discrete x positions based upon the time and you could see that area chart a bit clearer.
Sample time-based xAxis:
$(function() {
$('#container').highcharts({
chart: {
type: 'area'
},
xAxis: {
startOnTick: false,
type: 'datetime'
},
series: [{
name: 'John',
data: [0, 3, 4, 7, 2],
pointStart: Date.UTC(2010, 0, 0),
pointInterval: 5 * 3600 * 1000 // 5 hour
}, {
name: 'Jane',
data: [2, -2, -3, 2, 1],
pointStart: Date.UTC(2010, 0, 0),
pointInterval: 5 * 3600 * 1000 // 5 hour
}, {
name: 'Joe',
data: [3, 4, 4, -2, 5],
pointStart: Date.UTC(2010, 0, 0),
pointInterval: 5 * 3600 * 1000 // 5 hour
}]
});
});
What I mean "stylistically" is that you have hard breaks from "00:00" to "05:00". So let's assume that is 5 hours between categories. Does an area plot really convey any information to the user since you have a 5 hour gap between points? Wouldn't a simply column chart make more sense here? If this is even 5 minutes between categories it seems a little iffy to make this an area chart.
I am a bit confused by the documentation regarding the notation for point values when it comes to 3+ value charts such as HeatMap and BoxPlot.
I see that point values can be supplied as n length arrays:
data: [
[760, 801, 848, 895, 965],
[733, 853, 939, 980, 1080]...
]
And that they can be config objects with additional/custom properties:
data: [{
name: 'Point 1',
color: '#00FF00',
x: 1,
y: 3
}, {
name: 'Point 2',
color: '#FF00FF',
x: 2,
y: 5
}]
But how does one use the config object notation for HeatMap/BoxPlot when the only documented value properties seem to be 'x' and 'y'?
Is there a supported property of the config object that will be interpreted as the n length array? Something like this?
data: [{
name: 'Point 1',
color: '#00FF00',
values: [1,2,3]
}, {
name: 'Point 2',
color: '#FF00FF',
values: [4,5,6]
}]
It depends on the type of chart.
For HeatMap (reference):
A heat map has an X and Y axis like any cartesian series. The point definitions however, take three values, x, y as well as value, which serves as the value for color coding the point. These values can also be given as an array of three numbers.
In other words you could do { x: 0, y: 1, value: 10 } or [0,1,10].
For BoxPlot (reference):
Each point in a box plot has five values: low, q1, median, q3 and high. Highcharts recognizes three ways of defining a point:
Object literal. The X value is optional.
{ x: Date.UTC(2013, 1, 7), low: 0, q1: 1, median: 2, q3: 3, high: 4 }
Array of 5 values. The X value is inferred.
[0, 1, 2, 3, 4]
Array of 6 values. The X value is the first position.
[Date.UTC(2013, 1, 7), 0, 1, 2, 3, 4]
Highcharts does a great job figuring out appropriate tick intervals.
However, I have a "duration" series (in ms), which I format e.g. like "3y 6M" or "1d 3h" or "3h 30min" for display. Because Highcharts is optimizing the tick intervals for the ms value (e.g. 10,000,000ms), I end up with awkward values such as [ 2h 46min 40s, 5h 33min 20s, 8h 20min ] rather than [ 3h, 6h, 9h ].
Can I get Highcharts to prefer multiples of certain values (e.g. 1000, 60 * 1000, 60 * 60 * 1000 etc)? I'd rather not have to calculate the exact tick interval myself (depends on chart size etc).
I think you should consider using datetime axis for yAxis. For example: http://jsfiddle.net/jRGvs/
yAxis: {
type: 'datetime'
},
series: [{
type: 'column',
name: 'Column',
data: [Date.UTC(1970, 0, 1, 2, 30),
Date.UTC(1970, 0, 1, 1, 45),
Date.UTC(1970, 0, 1, 4, 10),
Date.UTC(1970, 0, 1, 3, 30)]
}]
you can go with label > formatter for yAxis,
here you can write a routine which will handle the text/value to be displayed beside the grid line. but the thing is you cannot override the tick interval from here.
As shown in the picture (which is not the same code as the fiddle, but exhibits the problem), with Highcharts new bubble charts it seems like dataLabels like to sit on top of each other. Is there an easy workaround for this? I'd be happy to manually change the z-index on a per label basis, but this doesn't seem to work for bubble charts. Here's some sample code that fails to work as expected (try it in a fiddle):
series: [{
data: [{
x: 99,
y: 36,
z: 50
}, {
x: 99,
y: 74,
z: 55,
dataLabels: {
zIndex:15,
enabled: true,
}
}, {
x: 99,
y: 76,
z: 55,
dataLabels: {
zIndex: 1,
enabled: true
}
}
]
}],
You can set useHTML: true flag, and then set z-index: x property for dataLabels, see: http://jsfiddle.net/ZLmU8/4/
Apparently there is a labelrank property on the Highcharts point objects that can be used to dictate which point labels are on top. It can be used when you're creating your data like this:
data: [{
x: 1, y: 1, labelrank: 1, name: 'A'
},{
x: 1, y: 1, labelrank: 2, name: 'B'
}]
Or it can be updated on an individual point to bring that point's dataLabel to the front by doing something like this: chart.series[0].points[0].update({labelrank: 3});
I had a similar issue and created this question on SO that just was answered.
Edit
They have added info regarding series.data.labelrank to their docs as well: http://api.highcharts.com/highcharts#series.data.labelrank