Monday, April 30, 2018

Google Charts Legend Position Top Not Working

Leave a Comment

You can use this jsfiddle for testing

Full Code:

google.load('visualization', '1.1', {     'packages': ['bar'] }); google.setOnLoadCallback(drawStuff);  function drawStuff() {     var data = new google.visualization.DataTable();     data.addColumn('string', 'Topping');     data.addColumn('number', 'Nescafe Instant');     data.addColumn('number', 'Folgers Instant');     data.addColumn('number', 'Nescafe Beans');     data.addColumn('number', 'Folgers Beans');     data.addRows([         ['2001', 500, 1200, 816, 200],         ['2002', 163, 231, 539, 594],         ['2003', 125, 819, 200, 578],         ['2004', 197, 536, 613, 500]     ]);      // Set chart options     var options = {         isStacked: true,         width: 800,         height: 600,         legend: {             position: "top",             alignment: "",             textStyle: {                     color: "#999"                 }             },         chart: {             title: 'Year-by-year coffee consumption',             subtitle: 'This data is not real'         },          series: {             2: {                 targetAxisIndex: 1             },             3: {                 targetAxisIndex: 1             }         }     };  }; 

Question :

I want to display legend above of the chart. I have used legend position : top. But it is not working. I can move legend either left side or right side without a problem changing legend position value.

But I can't move legend top or bottom. Why is that? What was the my mistake?

1 Answers

Answers 1

First, you need to use the correct library, as jsapi is out of date and should no longer be used,
according to the release notes.

The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader.js from now on.

This will only change the load statement:

old load statement...

google.load('visualization', '1.1', {   packages: ['bar'] }); 

new load statement...

google.charts.load('current', {   packages: ['corechart'] }); 

Next, as seen above, for classic charts, use --> packages: ['corechart']
instead of 'bar'

Google has provided a chart option, to style classic charts similar to material:

theme: 'material' 

When creating a classic chart, use the following namespace:

google.visualization.ColumnChart 

vs. material

google.charts.Bar 

See the following working snippet:

google.charts.load('current', {    packages: ['corechart']  }).then(function () {    var data = new google.visualization.DataTable();    data.addColumn('string', 'Topping');    data.addColumn('number', 'Nescafe Instant');    data.addColumn('number', 'Folgers Instant');    data.addColumn('number', 'Nescafe Beans');    data.addColumn('number', 'Folgers Beans');    data.addRows([      ['2001', 500, 1200, 816, 200],      ['2002', 163, 231, 539, 594],      ['2003', 125, 819, 200, 578],      ['2004', 197, 536, 613, 500]    ]);      var options = {      chartArea: {        height: '100%',        width: '100%',        top: 64,        left: 64,        right: 32,        bottom: 32      },      height: '100%',      width: '100%',      isStacked: true,      legend: {        position: 'top',        textStyle: {          color: '#999'        }      },      title: 'Year-by-year coffee consumption'    };      var container = document.getElementById('chart_div');    var chart = new google.visualization.ColumnChart(container);      drawChart();    window.addEventListener('resize', drawChart, false);    function drawChart() {      chart.draw(data, options);    }  });
html, body {    height: 100%;    margin: 0px 0px 0px 0px;    overflow: hidden;    padding: 0px 0px 0px 0px;  }    .chart {    height: 100%;  }
<script src="https://www.gstatic.com/charts/loader.js"></script>  <div class="chart" id="chart_div"></div>

Note: the only advantage to material is having multiple stacks,
in classic, you cannot group multiple stacks.


UPDATE

There are no options you can change to position the legend to top or bottom, it is simply not supported.

The only solution would be to manually build a custom legend; following is an example of how this could be done:

google.charts.load('current', {    packages: ['bar']  }).then(function () {    var data = new google.visualization.DataTable();    data.addColumn('string', 'Topping');    data.addColumn('number', 'Nescafe Instant');    data.addColumn('number', 'Folgers Instant');    data.addColumn('number', 'Nescafe Beans');    data.addColumn('number', 'Folgers Beans');    data.addRows([      ['2001', 500, 1200, 816, 200],      ['2002', 163, 231, 539, 594],      ['2003', 125, 819, 200, 578],      ['2004', 197, 536, 613, 500]    ]);      var options = {      chart: {        title: 'coffee consumption',        subtitle: 'This data is not real'      },      height: '100%',      isStacked: true,      legend: {        position: 'none'      },      series: {        2: {          targetAxisIndex: 1        },        3: {          targetAxisIndex: 1        }      },      width: '100%'    };      var container = document.getElementById('chart_div');    var chart = new google.charts.Bar(container);      drawChart();    window.addEventListener('resize', drawChart, false);    function drawChart() {      chart.draw(data, google.charts.Bar.convertOptions(options));    }      // add legend marker    function addLegendMarker(markerProps) {      var legendMarker = document.getElementById('template-legend-marker').innerHTML;      for (var handle in markerProps) {        if (markerProps.hasOwnProperty(handle)) {          legendMarker = legendMarker.replace('{{' + handle + '}}', markerProps[handle]);        }      }      document.getElementById('legend_div').insertAdjacentHTML('beforeEnd', legendMarker);    }      // chart ready event    google.visualization.events.addListener(chart, 'ready', function () {      var legend = document.getElementById('legend_div');        // get colors from chart      var colorPallette = [];      var colorsBottom = [];      var colorsTop = [];      var stacks = container.getElementsByTagName('*');      Array.prototype.forEach.call(stacks, function(stack) {        switch (stack.tagName) {          case 'path':            if ((stack.getAttribute('fill') !== null) && (stack.getAttribute('fill') !== '#ffffff')) {              if (colorsTop.indexOf(stack.getAttribute('fill')) === -1) {                colorsTop.push(stack.getAttribute('fill'));              }            }            break;            case 'rect':            if ((stack.getAttribute('fill') !== null) && (stack.getAttribute('fill') !== '#ffffff')) {              if (colorsBottom.indexOf(stack.getAttribute('fill')) === -1) {                colorsBottom.push(stack.getAttribute('fill'));              }            }            break;        }      });      for (var i = 0; i < colorsBottom.length; i++) {        colorPallette.push(colorsBottom[i]);        colorPallette.push(colorsTop[i]);      }        // clear previous legend      legend.innerHTML = '';        // add legend marker for each Y axis column - skip X axis --> i = 1      for (var i = 1; i < data.getNumberOfColumns(); i++) {        var markerProps = {};        markerProps.index = i;        markerProps.color = colorPallette[i - 1];        markerProps.label = data.getColumnLabel(i);        addLegendMarker(markerProps);      }        // add "hover" event to each legend marker      var currentSelection;      var markers = legend.getElementsByTagName('DIV');      Array.prototype.forEach.call(markers, function(marker) {        marker.addEventListener('mouseover', function (e) {          currentSelection = chart.getSelection();          var marker = e.target || e.srcElement;          if (marker.tagName.toUpperCase() !== 'DIV') {            marker = marker.parentNode;          }          var columnIndex = parseInt(marker.getAttribute('data-columnIndex'));          chart.setSelection([{column: columnIndex}]);        }, false);        marker.addEventListener('mouseout', function (e) {          chart.setSelection([]);        }, false);      });    });  });
html, body {    height: 100%;    margin: 0px 0px 0px 0px;    overflow: hidden;    padding: 0px 0px 0px 0px;  }    .chart {    height: 100%;  }    #legend_div {    color: #999;    font-family: Roboto;    position: absolute;    right: 0px;    text-align: right;    top: 0px;    width: 60%;    z-index: 1000;  }    .legend-marker {    display: inline-block;    padding: 6px 6px 6px 6px;  }    .legend-marker-color {    border-radius: 25%;    display: inline-block;    height: 12px;    width: 12px;  }
<script src="https://www.gstatic.com/charts/loader.js"></script>  <div id="legend_div"></div>  <div class="chart" id="chart_div"></div>    <!-- template for building marker -->  <script id="template-legend-marker" type="text/html">    <div class="legend-marker" data-columnIndex="{{index}}">      <div class="legend-marker-color" style="background-color: {{color}}"></div>      <span>{{label}}</span>    </div>  </script>

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment