3rgo
3rgo

Reputation: 3153

Is it possible to position Highcharts dataLabels depending on the value?

I'm using Highcharts to display a bar chart, with 2 bars overlaying each other, and a dataLabels at the right of them, displaying the exact value.

The problem here is that when the value is above 80%, the label is overflowing from the chart into the frame, going over some other text, and making them both unreadable.

Here are my plotOptions :

plotOptions: {
            bar: {
                groupPadding: 0.5,
                pointWidth : 30,
                borderWidth: 0,
                dataLabels: {
                    enabled: true,
                    y:-5,
                    color:"black",
                    style: {
                        fontSize: "12px"
                    },
                    formatter: function(){
                        if(this.y > 80)
                        {
                            this.series.chart.options.plotOptions.bar.dataLabels.x -= 20;
                        }
                        if(this.series.name == "Tests OK")
                            return "Tests OK : <strong>"+Math.round(this.y*10)/10+"%</strong>";
                        else
                            return "<br/>Tests Executed : <strong>"+Math.round(this.y*10)/10+"%</strong>";
                    }
                }
            }
        }

I thought i could edit the chart options on the go, using this.series.chart.options.plotOptions.bar.dataLabels.x -= 20;, but this doesn't work.

Surely I'm not the first one who has encountered a problem like that. Any idea ?

Thanks

Upvotes: 13

Views: 36879

Answers (4)

Bhesh Gurung
Bhesh Gurung

Reputation: 51030

Looks like it's not possible to do that from within the formatter.

But you could set them after the chart is rendered (loaded). Try something like this

$.each(chartObj.series[0].data, function(i, point) {
    if(point.y > 100) {
        point.dataLabel.attr({x:20});
    }
});

in the load callback (or if you need it in the redraw callback).

See example here.

Upvotes: 15

Jerod Venema
Jerod Venema

Reputation: 44632

Here's what I ended up with. The setTimeout is necessary or the dataLabel property doesn't exist on the point:

formatter: function () {
    var point = this.point;
    window.setTimeout(function () {
        if (point.s < 0) {
            point.dataLabel.attr({
                y: point.plotY + 20
            });
        }
    });
    //this.series.options.dataLabels.y = -6;
    var sty = this.point.s < 0 ? 'color:#d00' : 'color:#090;' //other style has no effect:(
    return '<span style="' + sty + '">' + Math.abs(this.point.s) + '</span>';
}

Upvotes: 6

simpixelated
simpixelated

Reputation: 51

Although Bhesh's answer solves the problem for x/y positioning, Highcharts ignores any changes to the style property of dataLabels (see the problem here). However, you can override the styles of an individual point by passing it through the data object:

series: [{ data: [29.9, 106, { y: 135, dataLabels: { style: { fontSize: 20 } } }]

example from Highcharts docs

I was able to get dynamic styles by iterating over my data before passing the whole object to Highcharts to render.

Upvotes: 4

Travis
Travis

Reputation: 1

I've been trying to figure some of this out myself... it looks like instead of

this.series.chart.options.plotOptions.bar.dataLabels.x -= 20;

could you use...

this.series.options.dataLabels.x = -20;

... at this point I'm trying to understand if I'm able to discern the location of a dataLabel so that I can reposition it if necessary.

Upvotes: 0

Related Questions