Individually Styling Data Labels for Bar Chart - highcharts

Is it possible to style individual data labels for a bar chart?
I would like to position each data label at the 0 axis point(for the chart) underneath each bar. However, if i signify x:0 for the data labels, it is different for each bar length. Can i get it to the 0 axis for the chart(with 5px padding:)
Thanks!

In such case you can translate that labels using simple hack, see:
events: {
load: function(){
for(var i = 0; i < this.series[0].data.length; i++) {
var d = this.series[0].data[i];
d.dataLabel.translate(0, d.dataLabel.y);
}
}
}
Live example: http://jsfiddle.net/zLE5R/2/

Related

HighCharts-XRange Series: how to restrict data labels width to stay within corresponding data point width

I am working with XRange charts in High Charts where I have custom data labels for my data points. I face a similar problem in 2 scenarios:
When data label text is longer than width of corresponding data point range, it overflows outside and onto adjacent data points and hides their label, like this:
When scrolling across the x-axis, the data labels slide across and overflow even when the data point range isn't wide enough to show. This looks quite confusing;
.
You would notice it looks even worse here;
.
How do I fix this so that the data labels never flow outside the extent of the data point?
I have tried tweaking the "inside" parameter but it only ensures that the label doesn't flow into an adjacent row. Similarly, I looked at the crop and overflow options in the API but couldn't get it to work for me as needed.
I understand the width option in style might let me address the first problem, but I can't have a common absolute value in pixels for all labels as the width of each is dynamic. Also, the second problem still wouldn't be solved.
You can find both issues re-created here : https://jsfiddle.net/td0bsxg1/4/ . I need to handle both of them as gracefully as possible.
Do I need to change some parameter for the data labels?
dataLabels: {
enabled: true,
defer: false,
inside: true,
formatter: function () {
return 'Too Long Data Label';
}
}
You can dynamically set individual width style for each data label and define rules for them:
events: {
render: function() {
if (redrawEnabled) {
var points = this.series[0].points,
chart = this,
dataLabelWidth,
width;
redrawEnabled = false;
Highcharts.each(points, function(point) {
width = point.shapeArgs.width;
if (width < 20) {
point.dataLabel.hide();
} else {
point.dataLabel.show();
}
point.dataLabel.css({
width: width
});
});
chart.series[0].isDirty = true;
chart.redraw();
redrawEnabled = true;
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/wo0q9nzr/

Highcharts yAxis labels inside plot area and left padding

I have a column chart that has yAxis labels inside the plot area. DEMO: http://jsfiddle.net/o4abatfo/
This is how I have set up the labels:
yAxis: {
labels: {
align: 'left',
x: 5,
y: -3
}
}
The problem is that the leftmost column is so near the plot area edge that labels are overlapping it. Is there a way to adjust the plot area padding so that the columns would start a bit further on the right?
You can set min value as -0.49.
http://jsfiddle.net/o4abatfo/2/
One possible solution:
Keep the labels on the outside, and apply the plotBackgroundColor as the chart backgroundColor.
This means that the legend will be encased in the background color too, but, again, it's on option.
Example:
http://jsfiddle.net/jlbriggs/o4abatfo/11/
I asked the same thing in the Highcharts forum and got this solution as a reply from #paweł-fus:
var chartExtraMargin = 30;
Highcharts.wrap(Highcharts.Axis.prototype, 'setAxisSize', function (p) {
p.call(this);
if (this.isXAxis) {
this.left += chartExtraMargin;
this.width -= chartExtraMargin;
this.len = Math.max(this.horiz ? this.width : this.height, 0);
this.pos = this.horiz ? this.left : this.top;
}
});
However, adding this made the tooltips appear in the wrong position. This was fixed by overriding the Tooltip.prototype.getAnchor() method and adding the extra margin in the x coordinate:
Highcharts.wrap(Highcharts.Tooltip.prototype, 'getAnchor', function(p, points, mouseEvent) {
var anchor = p.call(this, points, mouseEvent);
anchor[0] += chartExtraMargin;
return anchor;
});

Highcharts - resize legend on chart resize?

Is there anyway to dynamically set a specific width of legend items when resizing the chart? I have some really long item names possible in the legend so I need to specify a width to force the text to wrap, but I would like to change the width when the width the chart changes. Thanks.
I found a better work around for this:
chart.legend.options.width = newwidth;
chart.legend.itemStyle.width = newwidth;
for(var index in this.chart.series) {
chart.legend.destroyItem(chart.series[index]);
}
chart.legend.render()
Generally it is not possible, but you can disable highcharts legend, and prepare your own div (positioned absolutely) which will include list of all series and click event. Simple example is available here
$legend = $('#customLegend');
$.each(chart.series[0].data, function (j, data) {
$legend.append('<div class="item"><div class="symbol" style="background-color:'+data.color+'"></div><div class="serieName" id="">' + data.name + '</div></div>');
});
$('#customLegend .item').click(function(){
var inx = $(this).index(),
point = chart.series[0].data[inx];
if(point.visible)
point.setVisible(false);
else
point.setVisible(true);
});
http://jsfiddle.net/N3KAC/10/
Than only what you need is adapt this to your chart by catching $(window).resize() function and resize element.

HighCharts: Positioning label on chart agnostic of legend size

I am building a pie chart where the labels for the data points can very greatly in length, the legend is configured to be vertical and positioned on the left side.
I have added a label element to the bottom of the chart that shows the total of all data points.
The problem I am facing is that the positioning of this label (via the style element) is based on how wide the legend is, which occasionally if the legend is wide enough will be pushed off the right side of the chart.
Does anyone know of a way that I can style this label so that is positioned based solely on the width of the entire chart.
Here is the styling applied to the label (I tried adding the position value but this didn't appear to do anything):
style: {
top: '325px',
position: 'absolute',
left: '-160px',
'font-size': '175%'
}
Here is an example of the chart that I'm working with, you can see that the value for the total has bee cut off.
EDIT:
As per Sebastian's comment I was able to effectively solve the issue by using the legend label formatter to limit the length of the series names. Here is the code:
labelFormatter: function () {
var formattedName = this.name;
if (formattedName.length > 17) {
formattedName = formattedName.substr(0, 14) + '...';
}
return formattedName;
}
Have you tried to use labelFormatter http://api.highcharts.com/highcharts#legend.labelFormatter ?

highcharts grouped chart using custom bar width with no pointPadding

Basically i want to use pointPadding with custom bar width (pointWidth) both at the same time. But i can't, here is my problem:
I want a chart with no-padding in the bars of one group when showing grouped chart. For this purpose i used pointPadding: "0" and it shows me exactly right chart. like:
if(chart_json.chart.defaultSeriesType=='column'){
if(chart_json.xAxis.categories.length >= 1 ){
chart_json.plotOptions.column.groupPadding = "0.05";
chart_json.plotOptions.column.pointPadding = "0.00";
}
}
var chart=new Highcharts.Chart(chart_json,startupObj.startupFunction);
chartObjArray.push(chart);
But when i set my custom width it adds some spaces in between bars of one group.
Actually i want to put max and min limit on bar width, but i can't find any support from Highchart library. So for this purpose when highchart generate the chart, if the generated chart bar width exceeds my max-limit i set it to my max-limit and same for lower limit.
if(chart_json.chart.defaultSeriesType=='column'){
if(chart_json.xAxis.categories.length >= 1 ){
chart_json.plotOptions.column.groupPadding = "0.05";
chart_json.plotOptions.column.pointPadding = "0.00";
}
}
var chart=new Highcharts.Chart(chart_json,startupObj.startupFunction);
chartObjArray.push(chart);
//set bar width
if(chart_json.chart.defaultSeriesType=='column' || chart_json.chart.defaultSeriesType=='bar'){
setChartBarMaxMinWidth(chart,chart_json);
}
setChartContainerWidth(chart_json,chart);
////************************************///////////////////
function setChartBarMaxMinWidth(chart,json){
var maximumBarWidth=70;
var minimumBarWidth=15;
chart_json=eval('('+json.chart_json+')');
for(var j=0;j<chart.series.length;j++){
var series=chart.series[j];
if (series.data[0].pointWidth > maximumBarWidth) {
chart.series[j].options.pointWidth = maximumBarWidth;
isMaxMin='MAX';
}
if (series.data[0].pointWidth < minimumBarWidth) {
chart.series[j].options.pointWidth = minimumBarWidth;
isMaxMin='MIN';
}
};
function setChartContainerWidth(chartOptions,chart){
// calculate # of bars
var numberOfBars=seriesGroupLength*categoriesLength;
// calculate container width
// var containerWidth=numberOfBars*43;
// get chart bar width
var containerWidth=numberOfBars*barWidth;
chart.setSize($(container).width(),$(container).height());
};
In setChartContainerWidth() i used highchart setSize() method to resize chart..
Thanks if someone can help me to remove spaces in between bars of one group.
Thanks
I used the spacingTop attribute to enforce a maximum pointWidth:
if (series[0].data[0].pointWidth > maximumBarWidth) {
this.options.chart.spacingTop = this.options.chart.height - (maximumBarWidth * series.length) - 30;
this.isDirtyBox = true;
this.redraw();
}
So if there is one Bar over a certain Width the spacing will be adjusted and the chart is drawn smaller.
This does not change the size of the container but keeps the bars beneath a certain size and your pointPadding and groupPadding will not be affected.
You will have to adjust the calculation of the spacingTop depending on your data structure and the size of your axis titles.

Resources