Highcharts sorted stacked columns : position of labels

99 Views Asked by At

I need to sort a categorized stacked columns in Highcharts (sorting categories by totals and in each column, sorting series to ascending/descending).

I found the topic Highcharts: Sort column stack order to ascending that seems to be a great solution to achieve that.

The result is visible here : https://jsfiddle.net/vegaelce/0ye9objs/

The two things I would like to conclude are:

1/ place correctly the value labels (they don't follow the series sorting). I tried to change the datalabel y position with : stackedPoint.dataLabel.y = plotY; without success

2/ make functional the click on legend (when you clic on Jane for instance it does not result the expected behaviour). If it's not possible : just disable the click and let available the hover

Thanks

1

There are 1 best solutions below

5
ppotaczek On BEST ANSWER

I've updated the example a bit. There is an additional sortStacks function, which is called on chart load. Moreover, data-labels positions are corrected by using attr method and hidden series are ignored in the sortSeries function.

function sortStacks(chart) {
  const series = chart.series;
  const newSeries = [];
  let sortedPoints;

  series.forEach(s => {
    sortedPoints = [...s.points].sort((p1, p2) => p2.total - p1.total);
    s.setData(sortedPoints.map(p => p.y), false);
  });

  chart.xAxis[0].setCategories(sortedPoints.map(p => p.category));
}

function sortSeries(chart) {
  const series = chart.series;
  const yStart = chart.plotHeight;

  series[0].points.forEach((point, index) => {
    const points = series.map(s => s.points[index]);
    points.sort((p1, p2) => p2.y - p1.y);
    let lastY = 0;

    points.forEach((p, i) => {
      if (!p.series || !p.series.visible) {
        return false;
      }

      const newY = lastY ?
        lastY - p.shapeArgs.height :
        yStart - p.shapeArgs.height;

      lastY = newY;

      p.graphic.attr({
        y: newY
      });

      p.dataLabel.attr({
        y: newY + p.shapeArgs.height / 2 - p.dataLabel.height / 2
      });
      p.tooltipPos[1] = newY;
    });
  });
}

Highcharts.chart('container', {
  chart: {
    ...,
    events: {
      load: function() {
        sortStacks(this);
      },
      render: function() {
        sortSeries(this);
      }
    }
  },
  ...
});

Live demo: http://jsfiddle.net/BlackLabel/8fp96u1r/

API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#setData