lamarant
lamarant

Reputation: 3390

Highcharts display priority of overlapping labels

When data labels overlap in Highcharts, only one data label is displayed. This seems to be handled randomly. See fiddle:

http://jsfiddle.net/lamarant/rmxLd1d4/

$(function () {
    $('#container').highcharts({
        title: {
            text: 'Label Test'
        },
        series: [{
            type: 'line',
            data: [ 10, 10, 10, 10, 10, 10, 50],
            dataLabels: {
              enabled: true,
              color: 'blue',
              zIndex: 10
            },
            zIndex: 10
        },
        {
            type: 'line',
            data: [ 11, 11, 11, 11, 11, 11, 49],
            dataLabels: {
              enabled: true,
              color: 'red',
              zIndex: 10
            },
            zIndex: 20
        }]
    });
});

Notice that the first data label displayed in the chart is from the second series while the rest are from the first series.

I tried setting the priority of the label display using zIndex in both series and series.dataLabel with no luck.

Is there any way to set it so that a designated series always takes priority when Highcharts determines which label to display?

Upvotes: 1

Views: 1373

Answers (1)

Halvor Holsten Strand
Halvor Holsten Strand

Reputation: 20536

One possible fix is supplying a labelrank for each point, which is used to evaluate their sorting order. If you supply this rank for each point in a series, that series should be considered "above" series without such a rank (or with a lower rank integer value).

In code, manually for each point:

series: [{
    data: [ 
        { y: 11, labelrank: 1 }, 
        { y:11, labelrank: 1 } 
        // ...
    ],
    // ...
}]

In code, using the callback function (JSFiddle):

$('#container').highcharts({
    // Options ...
}, function() {
    var mySeriesIndex = 1;

    // For each point in the preferred series
    for(i = 0; i < this.series[mySeriesIndex].points.length; i++)
        // Set a labelrank
        this.series[mySeriesIndex].points[i].labelrank = 1;
});

My current take on the issue itself is this:

With the current implementation of the overlap logic it seems to me that this is a bit of an unintended behavior. The source code uses Array.sort in a way that shifts the positions of the point labels, since Array.sort is not guaranteed to be stable (same-value items wont retain their original order).

If you check your example in Firefox it should work as intended (their implementation of Array.sort is different), while in Chrome it doesn't (not stable). You could hope that this little feature is fixed.

Upvotes: 3

Related Questions