rredondo
rredondo

Reputation: 961

Highcharts, set legend height dynamically

I would like to set the height of the legend dynamically, so when the container gets resized, the legend height will be adjusted automatically. Ideally, the height of the legend should be half of the height of the charts container.

fiddle: https://jsfiddle.net/rredondo/awac1dw8/

Note that as the container gets smaller, the chart's plot area also becomes smaller until it disappears because the legend is taking up the space. This is the behavior I want to avoid. Also, I tried setting maxHeight to some number. The problem with this approach is that it is not dynamic, and it wastes a lot of space if the value is too small.

The legend options are:

legend: {
       align: 'center',
       verticalAlign: 'bottom',
       layout: 'vertical',
       enabled: true,
       //maxHeight: 150
},

The layout must be set to vertical, and the legend must be positioned below the chart.

Upvotes: 2

Views: 3969

Answers (2)

Kamil Kulig
Kamil Kulig

Reputation: 5826

Here's a solution that uses legend.update() on every chart redraw (it's also launched after the chart is rendered): https://jsfiddle.net/kkulig/2s8dnk6f/

The adjustLegendHeight function sets legend.maxHeight to a half of the chart's height:

function adjustLegendHeight(chart) {
  console.log(chart);
  chart.legend.update({
     maxHeight: chart.chartHeight / 2
  });
}

Notice that update function fires redraw within itself. To prevent infinite recursive calls I used global variable that controls radrawing:

events: {
  redraw: function() {
    if (redrawingEnabled) {
        // disable redrawing to prevent infinite recursive redraw() loop (update() fires redraw by default)
      redrawingEnabled = false; 

      adjustLegendHeight(this);

      // enable redrawing after update and redraw are finished
      redrawingEnabled = true; 
    }
  }
}

let redrawingEnabled = true;

function adjustLegendHeight(chart) {
  chart.legend.update({
    maxHeight: chart.chartHeight / 2
  });
}

var chart = Highcharts.chart('container', {
  chart: {
    plotBackgroundColor: null,
    plotBorderWidth: null,
    plotShadow: false,
    type: 'pie',
    events: {
      redraw: function() {
        if (redrawingEnabled) {
        	// disable redrawing to prevent infinite recursive redraw() loop (update() fires redraw by default)
          redrawingEnabled = false; 
          
          adjustLegendHeight(this);
     
          // enable redrawing after update and redraw are finished
          redrawingEnabled = true; 
        }
      }
    }
  },
  title: {
    text: ''
  },
  plotOptions: {
    pie: {
      allowPointSelect: true,
      cursor: 'pointer',
      dataLabels: {
        enabled: false
      }
    }
  },
  legend: {
    align: 'center',
    verticalAlign: 'bottom',
    layout: 'vertical',
    enabled: true
  },
  series: [{
    name: 'Brands',
    colorByPoint: true,
    showInLegend: true,
    data: [{
      name: 'Microsoft Internet Explorer',
      y: 56.33
    }, {
      name: 'Chrome',
      y: 24.03,
      sliced: true,
      selected: true
    }, {
      name: 'Firefox',
      y: 10.38
    }, {
      name: 'Safari',
      y: 4.77
    }, {
      name: 'Opera',
      y: 0.91
    }, {
      name: 'Proprietary or Undetectable',
      y: 0.2
    }, {
      name: 'Microsoft Internet Explorer',
      y: 56.33
    }, {
      name: 'Chrome',
      y: 24.03,
      sliced: true,
      selected: true
    }, {
      name: 'Firefox',
      y: 10.38
    }, {
      name: 'Safari',
      y: 4.77
    }, {
      name: 'Opera',
      y: 0.91
    }, {
      name: 'Proprietary or Undetectable',
      y: 0.2
    }, {
      name: 'Microsoft Internet Explorer',
      y: 56.33
    }, {
      name: 'Chrome',
      y: 24.03,
      sliced: true,
      selected: true
    }, {
      name: 'Firefox',
      y: 10.38
    }, {
      name: 'Safari',
      y: 4.77
    }, {
      name: 'Opera',
      y: 0.91
    }, {
      name: 'Proprietary or Undetectable',
      y: 0.2
    }]
  }]
});

adjustLegendHeight(chart);
#container {
  height: 100%;
  width: 250px;
  position: absolute;
}
<script src="https://code.highcharts.com/highcharts.js"></script>

<div id="container"></div>

Upvotes: 3

Andrew
Andrew

Reputation: 449

First of all, have you tried to use layout: 'horizontal' ? It splits the list of items in legend into parts, shows pretty neat pagination and resides in relativetily small space.

If not, I believe to manage chart legend you have no other options than digging down to API docs. If you look to the API reference provided there are plenty of options you can define to your chart. For example legend.lineHeight or legend.margin and others that can help to resize the legend container.

There is also a single method legend.update() where you can pass an object with new options to update your legend when needed.

So the trick is to track the size of the container/window and update it with wanted parameters. The similar way a chart made with ChartJS was resized here

Upvotes: 1

Related Questions