I have a column chart created using highcharts , where in I am showing list of student names in a class on x axis and average marks obtained on all the quiz he has taken on the y axis. For example student "abc" had scored 50 and 100 on two tests hence his average is 75. I want 75 to be displayed as value on column chart and on the tool tip i want to display "test 1 - 50","test 2 - 100".So inside series object i am passing in an array of average. Same will be done for other students in class.Help appreciated
You can put the test values as custom properties and refer to them in tooltip's formatter function:
series: [{
type: 'column',
data: [{
y: 75,
tests: [50, 100]
}, {
y: 50,
tests: [50, 50]
}]
}],
tooltip: {
formatter: function() {
var str = '';
this.point.tests.forEach(function(test, i) {
str += '<br>test' + (i + 1) + ' ' + test;
});
return str;
}
}
Live demo: http://jsfiddle.net/BlackLabel/t5f43zwn/
API Reference: https://api.highcharts.com/highcharts/tooltip.formatter
Related
I have a 3D stacked column chart.
If there is some larger values in the data, the small values will not be shown in the chart.
As you can see in
http://jsfiddle.net/43pv1a2q/6/
series: [{
name: 'John',
data: [500, 3, 4, 7, 2], //If change 500 to 5, all blocks will be shown
stack: 'male'
}, {
name: 'Joe',
data: [300, 4, 4, 2, 5], //change 300 to 3
stack: 'male'
},
{
name: 'Tom',
data: [500, 3, 4, 7, 2], // change 500 to 5
stack: 'male'
}]
The minPointLength works with bar chart, but not with stacked column chart.
https://api.highcharts.com/highcharts/series.columnrange.minPointLength
How do you set a minimum height for the block in a stacked column?
It seems to be a bug. You can report it here: https://github.com/highcharts/highcharts/issues
Workaround:
I update every point using a new value if its original y value is less than 50 (threshold) and save the original value in realValue property. Then I manually compute the cumulative values for every stack in tooltip.pointFormatter so that the viewer sees proper values:
events: {
load: function() {
var chart = this,
minColHeightVal = 50;
chart.series.forEach(function(s) {
s.points.forEach(function(p) {
if (p.y < minColHeightVal) {
p.update({
y: minColHeightVal,
realValue: p.y
}, false);
}
});
});
chart.redraw();
}
}
// (...)
pointFormatter: function() {
var stackSum = 0,
point = this,
chart = point.series.chart;
chart.series.forEach(function(s) {
s.points.forEach(function(p) {
if (p.x === point.x) {
stackSum += p.realValue ? p.realValue : p.y
}
});
});
return '<span style="color:' + this.color + '">\u25CF</span> ' + this.series.name + ': ' + (point.realValue ? point.realValue : point.y) + ' / ' + stackSum;
}
Live demo: http://jsfiddle.net/kkulig/j3toufk9/
The solution might be to set the y-axis to type: logarithmic, like so: http://jsfiddle.net/43pv1a2q/8/
yAxis: {
type: 'logarithmic',
allowDecimals: false,
title: {
text: 'Number of fruits',
skew3d: true
}
},
The only change I've made is to set "type: 'logarithmic' and removed "min: 0". I can't think of any other way to achieve what you're looking for when working with such hugely different numbers.
EDIT: Of course, you can still use "min: X" to set minimum value on the y-axis; I just removed it because it was unnecessary when I wanted minimum to default.
I am using highcharts to graph some datas. I can select two dates and the graph will show the datas between those 2 dates.
I have the following code:
options.xAxis[0] = {
type: 'datetime',
tickInterval: 3600 * 1000, // one hour
tickWidth: 5,
gridLineWidth: '1',
gridLineColor: gridLineColor,
labels: {
align: 'center',
x: -3,
y: 20,
formatter: function() {
return '<b style=\"font-size:120%\">' + Highcharts.dateFormat('%d-%m', this.value) + '<b>' + '<br>' + Highcharts.dateFormat('%l%p', this.value);
}
},
opposite: false
}
My problem is that if I have 1 day, I see all the hours and if I have selected 5 days for example, I see the 5 days on the axis but if I select 3 months, I see all the days within those 3 months. And this is unreadable.
Is it possible to say that you don't want to have more than 10 intervals shown on the axis?
Many thanks,
John.
You have a couple of options:
Set your tickInterval dynamically. Set the interval depending on time frame of your data
use the tickPixlInterval option. This decides on logical tick intervals that fall somewhere close to the pixel value you specify.
http://api.highcharts.com/highcharts#xAxis.tickPixelInterval
I am attempting to create a donut chart with (long) labels. The container for the chart is small (and dynamic). I keep running into a problem where the labels for the outer chart are cutoff.
series: [{
name: 'Browsers',
data: browserData,
size: '65%',
dataLabels: {
formatter: function() {
return this.y > 5 ? this.point.name : null;
},
color: 'white',
distance: -30
}
}, {
name: 'Versions',
data: versionsData,
size: '85%',
innerSize: '65%',
dataLabels: {
formatter: function() {
// display only if larger than 1
return this.y > 1 ? '<b>'+ this.point.name +':</b> '+ this.y +'%' : null;
}
}
}]
jsfiddle: http://jsfiddle.net/sw99B/
What I am trying to accomplish is the auto pie size, as is the case with simple pies:
series: [{
name: 'Versions',
data: versionsData,
dataLabels: {
formatter: function() {
// display only if larger than 1
return this.y > 1 ? '<b>'+ this.point.name +':</b> '+ this.y +'%' : null;
}
}
}]
jsfiddle: http://jsfiddle.net/4P4D5/
The problem with donuts is that I have to specify the size of the inner & outer donut. This causes the two pies making the donut to have fixed radius. Ideally, I would have the inner pie be a percentage of the outer; and let the outer pie have an auto-size.
Any suggestions on how to accomplish this?
The dataLabels: formatter... is only controlling whether or not to show datalabel for thinner slices. It's not controlling the size of the pie chart. That is being specified by the series:[{size parameter. In your example it's set to 85% of the container which does lead to overflow.
According to the docs
The default behaviour (as of 3.0) is to scale to the plot area and
give room for data labels within the plot area.
If you comment out the size on your example, it does indeed squeeze in the labels but I'm not sure you'll love the look of it.
The following minor patch to highcharts.src.js v4.0.1 achieves the desired behaviour:
--- highcharts.src.orig.js 2014-04-24 08:25:52.000000000 +0000
+++ highcharts.src.js 2014-06-24 13:57:42.957605307 +0000
## -12167,6 +12167,22 ##
positions = [pick(centerOption[0], '50%'), pick(centerOption[1], '50%'), options.size || '100%', options.innerSize || 0],
smallestSize = mathMin(plotWidth, plotHeight),
isPercent;
+
+ /**
+ * Allow a chart (pie) to specify a size relative to another series. In
+ * that case, simply copy the center position of the parent, and scale
+ * the radius.
+ */
+ if ( options.relativeSize ) {
+ parentPositions = chart.series[options.relativeSize.parentSeries].center;
+ positions[0] = parentPositions[0];
+ positions[1] = parentPositions[1];
+ positions[2] = options.relativeSize.size * parentPositions[2];
+
+ return map(positions, function (length, i) {
+ return positions[i]
+ });
+ }
return map(positions, function (length, i) {
isPercent = /%$/.test(length);
Then, when configuring the donut:
series: [{
name: 'Browsers',
data: browserData,
center: ['50%', '50%'],
dataLabels: {
formatter: function() {
return this.y > 5 ? this.point.name : null;
},
color: 'white',
distance: -30
}
}, {
name: 'Versions',
data: versionsData,
relativeSize: {
parentSeries: 0, // index of parent series
size: 0.75 // 75% of parent pie
}
dataLabels: {
formatter: function() {
// display only if larger than 1
return this.y > 1 ? ''+ this.point.name +': '+ this.y +'%' : null;
}
}
}]
Note that the parent (outer) pie must be explicitly centered in the container, otherwise in certain cases the two pies may not be concentric.
Also, requiring the index of the series to be specified is clearly not ideal, but in a tightly controlled graph (as is a donut), it seems to do the job.
Unfortunately this option is not available, so I advice you to post your request on the uservoice
I want to display couple of points on a highcharts line chart which are big numbers.
e.g. 100,000, 10,000,000, 1,000,000,000
When I display these, the y axis automatically formats the number into 100 k, 10 M, 1,000 M etc but the tooltip still shows the actual big number.
Is it possible to show 1,000,000,000 as 1 B or 1000 M in the tooltip itself.
Example - http://jsfiddle.net/ynCKW/1/
I am trying to play with the numberFormat function but I dont think its the right function.
Highcharts.numberFormat(this.y,0)
Do I have to write a custom function which would do this formatting in the tooltip?
You can use the same logic as implemented in Highcharts core:
tooltip: {
formatter: function () {
var ret = '',
multi,
axis = this.series.yAxis,
numericSymbols = ['k', 'M', 'G', 'T', 'P', 'E'],
i = numericSymbols.length;
while (i-- && ret === '') {
multi = Math.pow(1000, i + 1);
if (axis.tickInterval >= multi && numericSymbols[i] !== null) {
ret = Highcharts.numberFormat(this.y / multi, -1) + numericSymbols[i];
}
}
return ret;
}
},
And jsFiddle: http://jsfiddle.net/ynCKW/2/
EDIT for Highcharts v6:
We can call build-in method, which should be easier to maintain: http://jsfiddle.net/BlackLabel/ynCKW/104/
tooltip: {
valueSuffix: '',
formatter: function () {
var axis = this.series.yAxis;
return axis.defaultLabelFormatter.call({
axis: axis,
value: this.y
});
}
},
Piggybacking off #Pawel Fus, a slight tweak allows you to have negative currency values as well but with the negative outside the $ (i.e. -$100K versus -$-100k).
function () {
var isNegative = this.value < 0 ? '-' : '';
var absValue = Math.abs(this.value);
return isNegative + '$' + this.axis.defaultLabelFormatter.call({
axis: this.axis,
value: absValue
});
}
Here is a jsFiddle: http://jsfiddle.net/4yuo9mww/1/
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Set Additional Data to highcharts series
So I have this graph: http://jsfiddle.net/Gg3ZL/
And I want to replace in the tooltip where it currently says "Total Players Online" with new data from another
Array= ['PlayerX, PlayerY, PlayerZ', 'Player1, Player2, Player3'];
etc
So that it matches with the very first result in the first series data entry....
Even better if I didn't have to replace the "Total Players Online: " and instead just had another new entry in the tooltip like "Who's Online: ".
Basically mouse over an entry and see which players were online at that particular time on the tooltip.
Thanks for any help
You can attach the additional data with each point in the series.data as follows
series: [{
name: 'Series 1',
data: [{
y: 2,
players: ['a', 'b']},
{
y: 3,
players: ['a', 'b', 'c']},
{
y: 2,
players: ['x', 'y']},
{
y: 4,
players: ['a', 'b', 'c', 'd']}
]
}]
Now in the tooltip.formatter you can consume the additional data as follows
formatter: function() {
var result = '<b>' + Highcharts.dateFormat('%A, %b %e, %Y', this.x) + '</b>';
$.each(this.points, function(i, datum) {
result += '<br />' + datum.y + ' players online';
$.each(datum.point.players, function() {
result += '<br/>' + this;
});
});
return result;
}
Complex tooltip | Highchart & Highstock # jsFiddle