New to highcharts, but a simple question:
I need to mix several (say 6 or 8) small Highcharts gauges and charts on a single browser window. Is the only reliable way of doing this to create a separate div for each one and to target a separate Highcharts instance at each div?
And as a supplementary: Even if there is an alternative approach, is this multi-div approach as good as any, or are there pros and cons?
Here is how I do multiple Highcharts on the same page.
http://jsfiddle.net/no1uknow/Jb2cb/2/
Keep in mind that you'll want to use jQuery 1.9.1 and Highcharts JS 3.0.x+, if you want to support most all browsers including IE8. This jsfiddle demo will work cross browser.
There are many examples using "var chart" singular for every chart, but I like making a var container_chartname for each div container. This technique gives me a lot more control to be interactive with each chart on the fly. Like resize, update data, etc.
If you plan on using forms to build charts dynamically then you can also use "just" the javascript code in the above jsfiddle example as the json callback. This will load all the divs each time you hit submit on a form dynamically.
Stackoverflow requires me to post code here, but see jsfiddle for the full piece of code...
And of course this is just my technique, there are many others...
var container_chartCorrectiveAction = new Highcharts.Chart({
chart: {
renderTo: 'container_chartCorrectiveAction',
type: 'bar',
height: 195
},
title: {
text: 'Corrective Action'
},
subtitle: {
text: 'Sub-ATA () / ATA (20)'
},
xAxis: {
categories: ['No Defects Found-Fastener-Loose / Displaced'],
title: {
text: 'Action'
},
labels: {
style: {
width: '12000px'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Count',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
formatter: function() {
return ''+ this.series.name +': '+ this.y +' Count';
}
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
},
series: {
pointWidth:10,
groupPadding: .05,
shadow: true
}
},
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom',
floating: false,
borderWidth: 1,
backgroundColor: '#FFFFFF',
shadow: true,
labelFormatter: function() {
return '<div class="' + this.name + '-arrow"></div><span style="font-family: \'Advent Pro\', sans-serif; font-size:12px">' + this.name +'</span><br/><span style="font-size:10px; color:#ababaa"> Total: ' + this.options.total + '</span>';
}
},
credits: {
enabled: false
},
exporting: {
enabled: true
},
series: [{
name: 'Heavy',
total: '0',
data: [null]
},{
name: 'Intermediate',
total: '0',
data: [null]
},{
name: 'Line',
total: '0',
data: [null]
},{
name: 'Lite',
total: '1',
data: [1]
}]
});
var container_chartAtaFleetAvg = new Highcharts.Chart({
chart: {
renderTo: 'container_chartAtaFleetAvg',
type: 'bar',
height: 185
},
title: {
text: 'Fleet Average'
},
subtitle: {
text: 'ATA (20)'
},
xAxis: {
categories: ['Fleet Average'],
title: {
text: ''
},
labels: {
style: {
width: '12000px'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Average',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
formatter: function() {
return ''+ this.series.name +': '+ this.y +' Average';
}
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
},
series: {
pointWidth:10,
groupPadding: .05,
shadow: true
}
},
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom',
floating: false,
borderWidth: 1,
backgroundColor: '#FFFFFF',
shadow: true,
labelFormatter: function() {
return '<div class="' + this.name + '-arrow"></div><span style="font-family: \'Advent Pro\', sans-serif; font-size:12px">' + this.name +'</span><br/><span style="font-size:10px; color:#ababaa"> Total: ' + this.options.total + '</span>';
}
},
credits: {
enabled: false
},
exporting: {
enabled: true
},
series: [{
name: 'Intermediate',
total: '0.35',
data: [0.35]
},{
name: 'Lite',
total: '0.3',
data: [0.30]
},{
name: 'Heavy',
total: '0.1',
data: [0.10]
}]
});
You can also use many series in one div. http://jsfiddle.net/sbochan/wzprF/
It seems that the only way to do this is to have a container by chart.
In my own opinion, I don't think a multi-div approach is a bad idea. Just be careful about the id you will give to the div.
But you can create a clean code, on the javascript side. When you create many charts (6 or 8 is a lot...), you have to avoid code duplication... (At least to limit duplication)
There is a good way to do this with jQuery.extend() and Highcharts.setOptions : Manage multiple highchart charts in a single webpage
Make sure your div containers are formatted as this
<div ... ></div>
and not
<div ... />
as it may not render properly.
Related
I'm newbie to highchart and I've got a demo for polar chart using highcharts
Highcharts.chart('container', {
chart: {
polar: true,
type: 'area'
},
accessibility: {
description: 'ASDFR'
},
title: {
text: '',
x: -120
},
pane: {
size: '100%',
startAngle:-42
},
xAxis: {
categories: ['ATT', 'TEC', 'TAC', 'DEF', 'CRE'],
tickmarkPlacement: 'on',
lineWidth: 0,
labels:{
formatter: function(){
return this.value + '???'
}
}
},
yAxis: {
gridLineInterpolation: 'polygon',
},
tooltip: {
shared: true,
pointFormat: '<span style="color:{series.color}">{series.name} <b>{point.y:,.0f}</b></span>'
},
legend: {
align: 'right',
verticalAlign: 'middle',
layout: 'vertical'
},
series: [{
name: '',
data: [73, 80, 80, 54, 92],
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
align: 'center',
verticalAlign: 'bottom',
layout: 'horizontal'
},
pane: {
size: '70%'
}
}
}]
}
});
How can I show the value of the series right in the xAxis label e.g ATT 73, TEC 80, TAC 80...
You can get the associated value through series data. Example:
xAxis: {
...,
labels: {
formatter: function() {
return this.value + ' ' + this.chart.series[0].yData[this.pos];
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/pyohzk8c/
API Reference: https://api.highcharts.com/highcharts/xAxis.labels.formatter
I'm creating a heatmap from highcharts that shows the allocation to different asset classes for multiple portfolios. The y-axis contains asset classes and the x-axis contains the portfolios (1 - 20).
The heatmap I've constructed looks very much like the one in this demo: https://www.highcharts.com/demo/heatmap. What I would like to do is to essentially construct a heatmap per column (or per portfolio). Is this possible with highcharts?
I'm using the code below to construct the heatmap currently:
Highcharts.chart('portfolioChart', {
chart: {
type: 'heatmap',
height: 700
},
title: {
text: 'After-tax Portfolio Composition'
},
xAxis: {
categories: json.columns,
align: 'top'
},
yAxis: {
categories: json.index,
title: null,
reversed: true
},
colorAxis: {
min: 0,
minColor: '#fff',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 600
},
tooltip: {
formatter: function() {
return '<b>' + this.series.xAxis.categories[this.point.x] + ', ' + this.series.yAxis.categories[this.point.y] + '</b> = ' + (this.point.value*100).toFixed(1) + '%'
}
},
series: [{
name: 'Portfolio Allocation',
borderWidth: 1,
data: portfolioData,
dataLabels: {
enabled: true,
color: '#000',
formatter: function() {
return (this.point.value * 100).toFixed(1) + '%';
}
}
}]
});
I was wondering if anyone was able to create a bar chart with labels like the pie chart? I need to be able to create the labels outside and create that line to them. Just like the pie chart does here:
http://www.highcharts.com/demo/pie-basic
I have a basic bar chart (using it as a progress bar). I need to create the labels on the outside because the sections might get really small. Here is my JSFiddle: http://jsfiddle.net/rLYj4/5
$(function () {
$('#container').highcharts({
chart: {
type: 'bar'
},
title: {
text: '<b>Total</b><br/><b>$100.00</b>'
},
exporting: {
enabled: false
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
gridLineWidth: 0,
minorGridLineWidth: 0,
gridLineColor: 'transparent',
startOnTick: false
},
yAxis: {
minorGridLineWidth: 0,
gridLineWidth: 0,
gridLineColor: 'transparent',
labels: {
enabled: false
},
title: {
text: ''
}
},
legend: {
enabled: false
},
tooltip: {
formatter: function() {
return this.series.name +': '+ this.y +'<br/>'+
'Total: '+ this.point.stackTotal;
}
},
plotOptions: {
series: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: 'white'
}
}
},
series: [{
name: 'Category 1',
data: [50.00]
}, {
name: 'Category 2',
data: [25.00]
}, {
name: 'Category 3',
data: [12.50]
}, {
name: 'Category 4',
data: [12.50]
}]
});
});
Does anyone know how to accomplish this?
Thanks,
Joshua
Unfortuantely this option is not supported, but you can post your suggestion on the website: http://highcharts.uservoice.com/forums/55896-general
I have a custom HighCharts that have totals in the legend. I need to add one line of custom text centered under the totals "in the legend". Also I need to add text center at the bottom of the chart "under the legend".
See fiddle:
http://jsfiddle.net/no1uknow/cvsTB/
[EDIT]
I did figure this much out but don't know how to get text centered under legend.
http://jsfiddle.net/no1uknow/cvsTB/1/
$(function () {
var chart;
$(document).ready(function() {
var container_chartFreqAtaTailNum = new Highcharts.Chart({
chart: {
renderTo: 'container_chartFreqAtaTailNum',
type: 'bar',
height: 795
},
title: {
text: 'Frequency by Tail Number'
},
subtitle: {
text: 'Fact ATA (25)'
},
xAxis: {
categories: ['235','245','402','411','432','442','493','703','714','720','730','745','756','767','772','792'],
title: {
text: 'Tail Number'
},
labels: {
style: {
width: '12000px'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Count',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
formatter: function() {
return ''+ this.series.name +': '+ this.y +' Count';
}
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
},
series: {
pointWidth:10,
groupPadding: .05,
shadow: true
}
},
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom',
floating: false,
borderWidth: 1,
backgroundColor: '#FFFFFF',
shadow: true,
labelFormatter: function() {
return '<div class="' + this.name + '-arrow"></div><span style="font-family: \'Advent Pro\', sans-serif; font-size:12px">' + this.name +'</span><br/><span style="font-size:10px; color:#ababaa"> Total: ' + this.options.total + '</span>';
}
},
credits: {
enabled: false
},
exporting: {
enabled: true
},
series: [{
name: 'Heavy',
total: '5421',
data: [117,102,698,640,251,115,269,279,260,309,328,427,316,754,239,317]
},{
name: 'Intermediate',
total: '4888',
data: [299,169,448,532,210,256,241,295,226,368,319,420,272,243,313,277]
},{
name: 'Line',
total: '659',
data: [29,38,50,47,33,27,22,67,57,44,36,53,41,37,35,43]
},{
name: 'Lite',
total: '2172',
data: [101,116,139,124,123,139,148,249,168,141,122,136,91,154,105,116]
}]
});
});
});
spacingBottom is what you need to add, and also you need to take care of the offset:
chart: {
events: {
load: function () {
var label = this.renderer.label("How do I move this center and under the legend.")
.css({
width: '450px',
color: '#222',
fontSize: '16px'
})
.attr({
'stroke': 'silver',
'stroke-width': 2,
'r': 5,
'padding': 10
})
.add();
label.align(Highcharts.extend(label.getBBox(), {
align: 'center',
x: 0, // offset
verticalAlign: 'bottom',
y: 50 // set the right offset
}), null, 'spacingBox');
}
},
renderTo: 'container_chartFreqAtaTailNum',
type: 'bar',
height: 895,
spacingBottom: 100 // The space between the bottom edge of the chart and the content (plot area, axis title and labels, title, subtitle or legend in top position).
}
Here is the fiddle: http://jsfiddle.net/uMBHf/1/
I have a chart that looks like this:
http://jsfiddle.net/rtGFm/37/
I would like to have a "sort" button that sorts high to low each category, putting the columns in a different order for each category. Is this possible with HighCharts?
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: ''
},
subtitle: {
text: ''
},
xAxis: {
categories: [
'foreclosures',
'nuisances',
'distance from city center'
]
},
yAxis: {
min: 0,
title: {
text: ''
}
},
tooltip: {
formatter: function() {
return ''+
this.x +': '+ this.y +' mm';
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Alger Heights',
data: [49.9, 71.5, 50]
}, {
name: 'Shawmut Hills',
data: [83.6, 78.8, 67]
}, {
name: 'Baxter',
data: [48.9, 38.8, 100]
}, {
name: 'Midtown',
data: [42.4, 33.2, 80]
}, {
type: 'scatter',
data: [55,60,70],
marker: {
symbol: 'square',
lineColor: '#FFFFFF',
lineWidth: 1,
radius: 8
},
name: 'Average'
}]
});
});
I had the same problem :) highcharts still does not provide any solution for this problem, but it is flexibel enough so that you can sort anyway - just by javascript.
Put your data in a separate value:
var dataMain = [{name:"test1",data:5}, {name:"test1",data:1},{name:"test1",data:2}]
In series you can just add a function which sorts your data:
series: (function(){
for(var i = 0;i<dataMain.length;i++){
dataMain[i].data = dataMain[i].data.sort(function(a,b){
return a[0] - b[0] ;
})
return dataMain;
}
Hope I got everything wright.
Got it to work, I believe. Trick is to add each column in correct order as a new serie with same type (column), reuse colors and hide legend...
Very hackish, the JS code to sort like 8 categories independently will be ugly but the result looks fine.
Edit: Updated fiddle, I see the spacing between the categories grows with series, doesn't look supernice.
My jsfiddle is here
$(function () {
$('#container').highcharts({
chart: {
inverted: true
},
title: {
text: 'Series sorted in within categories'
},
xAxis: {
categories: ['January']
},
series: [{
type: 'column',
name: 'Stockholm',
data: [{x:0, y:95, color: Highcharts.getOptions().colors[0]}]
}, {
type: 'column',
name: 'Göteborg',
data: [{x:0, y:80, color: Highcharts.getOptions().colors[1]}]
}, {
type: 'column',
name: 'Göteborg',
data: [{x: 1, name: 'February', y: 98, color: Highcharts.getOptions().colors[1] // VGR's color
}],
showInLegend: false,
dataLabels: {
enabled: false
}
}, {
type: 'column',
name: 'Stockholm',
data: [{x: 1, name: 'February', y: 80, color: Highcharts.getOptions().colors[0] // VGR's color
}],
showInLegend: false,
dataLabels: {
enabled: false
}
}]
});
});
br,
Jens
I think this can be done,
this may look like a little work around.
since we have a limited number of columns i mean 4 in the given example.
if we have arrays with sorting done with respect to each series then we can handle them.
on button click we can update the chart with new set of data as well as category array.
May be there is no solution from the APi.
According to me this is a possible approach.
Thanks,