I'm trying to create a simple column chart using Highcharts. I want to be able to show legends at the bottom with legend symbols having same color as bars followed by the value and category. For some reason, I only see the first legend symbol. Here is the source https://jsfiddle.net/DeanSharma/gjbfj0rg/
$(function() {
var categories = ["Open","Expire within 90 days","In Progress","Past"],
colors = ["#1097ae","#81cbd6","#b4d66c","#317fc2"],
data = [9,13,7,8];
var chartData = [{y: 9, color: '#1097ae', name: 'Open'}, {y: 13, color: '#81cbd6', name: 'Expire within 90 days'}, {y: 7, color: '#b4d66c', name: 'In Progress'}, {y: 8, color: '#317fc2', name: 'Past'}];
var customLegend = '<div class="legend" style="vertical-align: bottom; background-color: transparent">';
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
height: 400,
marginBottom: 100,
align: 'top'
},
title: {text:'My Custom Column Chart', align:'center', style:{"font-size":'14px',"color":'#0000ff'}},
colors: colors,
legend: {
align: 'center',
enabled: true,
floating: true,
symbolWidth: 0,
labelFormatter: function() {
for(index=0; index< categories.length; index++) {
customLegend += '<div style="background-color:' + colors[index] + ' ; width:12px; height:12px;"></div>';
customLegend += '<div class="legend__value">' + data[index] + ' </div>';
customLegend += '<div class="legend__name">' + categories[index] + ' </div>';
customLegend += '<br />';
};
customLegend += '</div>';
return customLegend;
},
layout: 'horizontal',
verticalAlign: 'bottom',
y: 10
},
credits: {enabled: true, text: 'Courtesy DeanS', href:'stackoverflow.com'},
xAxis: {
categories: categories,
labels: {autoRotation: false,
style: {color: '#777',fontFamily: 'Open Sans',fontSize: '10px'}
},
lineColor: '#f8f8f8',
tickColor: '#f8f8f8'
},
yAxis: {
title: {
text: '',
useHTML: true
}
},
series: [{
data: chartData
}]
});
});
To achieve that result you do not need a custom legend. You can split your points into seperate series, disable grouping and then in the label formatter - return the point's value and the category.
plotOptions: {
series: {
grouping: false
}
},
series: data.map((point, i) => {
return {
data: [
[i, point]
]
}
})
Legend config:
legend: {
labelFormatter: function() {
return data[this.index] + ' ' + categories[this.index];
},
layout: 'vertical',
},
example: https://jsfiddle.net/gjbfj0rg/1/
Related
How can I move the below datalabel football in the top right of the variable pie chart instead of showing in bottom. I tried these options
alignTo: 'connectors' or alignTo: 'toPlotEdges'
But nothing worked for me. Any help will be appreciated
var total = 80;
Highcharts.chart('container', {
chart: {
type: 'variablepie',
height: 370,
marginBottom: 50
},
credits: {
enabled: false
},
title: {
text: 'Football vs cricket',
align: 'center',
y: -5,
verticalAlign: 'bottom',
style: {
fontFamily: 'proxima_nova_bold',
fontSize: '20px',
fontWeight: 'normal',
color: '#8d99ab',
}
},
subtitle: {
text: ' ' + total + '<br/> Total',
useHTML: true,
verticalAlign: 'middle',
y: -20
},
xAxis: {
labels: {
rotation: 0
}
},
plotOptions: {
variablepie: {
size: 220,
dataLabels: {
enabled: true,
connectorColor: '#979797',
useHTML: true,
formatter: function () {
var key;
if(this.key == 'football'){
key = 'as football / Lionel Messi';
}else if(this.key == 'cricket'){
key = 'as cricket / Sachin Tendulkar';
}else{
key = this.key;
}
return '<span class=cls1>' + this.y + '</span>' + '<span class=cls2>' + key + '</span>';
}
},
showInLegend: true,
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ this.y +' %';
}
},
legend: {
enabled: false
},
series: [{
minPointSize: 10,
innerSize: '70%',
zMin: 0,
data: [{name: "football", y: 71, z: 30}, {name: "cricket", y: 2, z: 18}]
}]
});
https://jsfiddle.net/anikettiwari/Lr3zy8qc/2/
You can try to implement one of the options showed here: https://www.highcharts.com/docs/advanced-chart-features/pie-datalabels-alignment
Or use the render callback and set the y position of this particular label manually.
Demo: https://jsfiddle.net/BlackLabel/2oskhmnd/
events: {
render() {
let chart = this;
chart.series[0].points[0].dataLabel.attr({y: 10});
chart.series[0].points[0].connector.hide();
}
}
Unfortunately, this solution requires to render the custom connector to moved dataLabel. You can do it by using some of the methods shown in the above link (pie-datalabels-alignment) or by using SVGRenderer tool to render a path: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path
API: https://api.highcharts.com/highcharts/chart.events.render
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) + '%';
}
}
}]
});
Trying to increase bar height to accommodate series name inside bar and trying to reduce default gap between series group. The section "series: []" is, I assume for the JSON return function to populate. Tried many examples from all the generous JSFiddle examples to no avail. I'm a noob so please be patient. Any ideas? So far I have: http://jsfiddle.net/PeterHanekom/7ue5bkm8/1/
var options = {
chart: {
renderTo: 'container',
type: 'bar'
},
colors: ['#00B9B9', '#527CED', '#A7D36B', '#B9B900', '#0097FF', '#400040', '#EA4D00', '#336699', '#8080C0', '#ADA870'],
title: {
text: 'Cluster Totals',
x: -20 //center
},
subtitle: {
text: 'Dept - Branch',
x: -20
},
xAxis: {
categories: []
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Percentage'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
this.x +': '+ this.y;
}
},
legend: {
align: 'center',
borderWidth: 0
},
plotOptions: {
bar: {
stacking: 'normal',
pointWidth: 20,
pointPadding: 0,
cursor: 'pointer',
point: {
events: {
click: function() {
alert('later drilldown events');
}
}
dataLabels: {
enabled: true,
inside:true,
useHTML: true,
align: 'left',
color: 'white',
style: {
fontWeight: 'bold'
},
verticalAlign: 'middle',
formatter: function () {
if (this.series.name)
return '<span style="color:black; height: 25px;">' + this.series.name + ' = ' + this.y + '</span>';
else return '';
}
}
}
},
series: []
}
$.getJSON("./services/get360Pivot.php?s_Search=" + sOperatorSearch, function(json)
{
options.xAxis.categories = json[0]['data'];
options.series[0] = json[1];
options.series[1] = json[2];
options.series[2] = json[3];
options.series[3] = json[4];
chart = new Highcharts.Chart(options);
});
I think you options you need are groupPadding and pointWidth. e.g.
groupPadding:0.1,
pointWidth:20,
http://jsfiddle.net/s3t2pL94/
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 am having a problem updating my basic column high chart.
My json array that is returned from the server is:
[{"name":"positive","data":[18,35,32,38]},{"name":"negative","data":[0,14,65,121]}]
I am only using the "data" arrays ^ i.e. jsonArr[0].data and jsonArr[1].data
I have the data set up correctly, however the chart is not depicting these values. Any ideas?
Here is my javascript:
$(document).ready(function() {
var twitterChart;
posArr = [];
negArr = [];
function renderGraph()
{
$.getJSON("FrontController", function(jsonArr, statusTxt, xhr){
console.log("Data returned : " + data);*/
posArr = jsonArr[0].data;
negArr = jsonArr[1].data;
console.log("posArr: " + posArr);
console.log("negArr: " + negArr);
twitterChart.series[0].data = posArr;
twitterChart.series[1].data = negArr;
});
setTimeout(renderGraph, 3000)
}
twitterChart = new Highcharts.Chart({
chart: {
renderTo: 'container1',
type: 'column'
},
title: {
text: ''
},
subtitle: {
text: ':'
},
xAxis: {
categories: [
'Column 1',
'Column 2',
'Column 3',
'Column 4'
]
},
yAxis: {
min: 0,
title: {
text: 'Testing"'
}
},
legend: {
layout: 'vertical',
backgroundColor: '#FFFFFF',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 70,
floating: true,
shadow: true
},
tooltip: {
formatter: function() {
return ''+
this.x +': '+ this.y +' tweets';
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Positive',
data: posArr
}, {
name: 'Negative',
data: negArr
}]
});
renderGraph();
});
</script>
To update series data use twitterChart.series[0].setData(array); see: http://api.highcharts.com/highcharts#Series.setData()