Custom Legend multiple colors in Google Chart
Asked Answered
C

1

1

I am facing a problem that I cannot custom the default legend color of this chart to multiple colors, please help me. This is image describe my problem , I am using stacked bar chart. This is my code:

//dump data arr
var data = google.visualization.arrayToDataTable([[["","0 times (never)",{"role":"style"},"1 times",{"role":"style"},"2 times",{"role":"style"},"3 times or more",{"role":"style"}],["A class",0.581,"#b4ddfd",0.109,"#84bfef",0.21,"#559ad2",0.1,"#4277a1"],["nationality",0.481,"#ffddba",0.209,"#ffc384",0.25,"#ffac5b",0.06,"#fa993f"]],[["","0 times (never)",{"role":"style"},"1 times",{"role":"style"},"2 times",{"role":"style"},"3 times or more",{"role":"style"}],["A class",0.1,"#b4ddfd",0.2,"#84bfef",0.3,"#559ad2",0.4,"#4277a1"],["nationality",0.4,"#ffddba",0.3,"#ffc384",0.2,"#ffac5b",0.1,"#fa993f"]],[["","0 times (never)",{"role":"style"},"1 times",{"role":"style"},"2 times",{"role":"style"},"3 times or more",{"role":"style"}],["A class",0.5,"#b4ddfd",0.5,"#84bfef",0,"#559ad2",0,"#4277a1"],["nationality",0,"#ffddba",0,"#ffc384",0,"#ffac5b",1,"#fa993f"]],[["","0 times (never)",{"role":"style"},"1 times",{"role":"style"},"2 times",{"role":"style"},"3 times or more",{"role":"style"}],["A class",0.01,"#b4ddfd",0.02,"#84bfef",0.03,"#559ad2",0.94,"#4277a1"],["nationality",0.4,"#ffddba",0.3,"#ffc384",0.2,"#ffac5b",0.1,"#fa993f"]]]);
var options = {
        series: {
            0: {
                color: '#b4ddfd'
            },
            1: {
                color: '#84bfef'
            },
            2: {
                color: '#559ad2'
            },
            3: {
                color: '#4277a1'
            },
        },
        vAxis: {
            textStyle: {fontSize: 11},
            titleTextStyle: {italic: false},
        },
        chartArea: {
            width: '85%',
            height: areaHeight,
            top: 30,
            left: '13%'
        },
        bar: {groupWidth: '35%'},
        legend: {
            position: 'bottom',
            textStyle: {fontSize: 11},
        },
        isStacked: 'percent',
        hAxis: {
            ticks: [0, 1],
            textStyle: {fontSize: 13},
            minValue: 0,
            maxValue: 1,
        },
        callbackLegend: function(legend) {
            // my problem here
            // var legend_div = document.getElementById(graphId + '_legend');
            // legend_div.innerHTML = legend.innerHTML;
        },
        width: 920,
        height: areaHeight + 100
    };
var chart = new google.visualization.BarChart(document.getElementById('#chart_div'));
    chart.draw(data, options);

Please help me, I am deadlocking.

Coppery answered 15/2, 2022 at 9:25 Comment(2)
here is an example that builds a custom legend that you may be able to adapt. not sure where you found callbackLegend but it doesn't work for this type of chart...Eicher
I've read your ref, but I cannot understand it, I'm beginner. May you write a few lines of explanation, please?Coppery
E
1

the standard legend on a google chart will not display multiple colors.
in fact, when using the style column role,
the legend will not match the colors used in the style columns in the data table.

instead, we can build a custom legend to display the multiple colors for each series.

to build the legend, we need to add a container to hold the legend entries.
we can use a <div> element placed just below the chart.

<div id="chart_div"></div>
<div id="legend_div"></div>

we can use css to style the legend container and use the same width of the chart.

#legend_div {
  font-family: Arial;
  font-size: 11px;
  text-align: center;
  width: 920px;
}

in the following example, I extract the colors for each series from the data table.
using the values provided in the style column roles.
to create the legend content, I use the following html templates.

one for the legend entry itself...

<script id="template-legend-entry" type="text/html">
  <div class="legend-entry" data-columnIndex="{{index}}">
    {{colors}}
    <span>{{label}}</span>
  </div>
</script>

and another for each color to be displayed for that series...

<script id="template-legend-entry-color" type="text/html">
  <div class="legend-entry-color" style="background-color: {{color}}"></div>
</script>

in this example, only two rows exist in the data table,
so two colors will be displayed for each legend entry.

the legend is built during the chart's 'ready' event,
so as soon as the chart is finished drawing,
the legend will be displayed.

during which, the colors are extracted from the data table and used to build the legend entries.

a click event is added for example purposes, in case there are actions you would like to take when a legend entry is clicked.
in this example, the chart series is selected to highlight which legend entry was clicked.

google.charts.load('current', {
  packages: ['corechart']
}).then(function () {
  var data = google.visualization.arrayToDataTable([
    ["","0 times (never)",{"role":"style"},"1 times",{"role":"style"},"2 times",{"role":"style"},"3 times or more",{"role":"style"}],
    ["A class",0.581,"#b4ddfd",0.109,"#84bfef",0.21,"#559ad2",0.1,"#4277a1"],
    ["nationality",0.481,"#ffddba",0.209,"#ffc384",0.25,"#ffac5b",0.06,"#fa993f"]
  ]);

  var options = {
    vAxis: {
      textStyle: {
        fontSize: 11
      },
      titleTextStyle: {
        italic: false
      }
    },
    chartArea: {
      width: '85%',
      top: 30,
      left: '13%'
    },
    bar: {
      groupWidth: '35%'
    },
    legend: {
      position: 'none'
    },
    isStacked: 'percent',
    hAxis: {
      ticks: [0, 1],
      textStyle: {
        fontSize: 13
      },
      minValue: 0,
      maxValue: 1
    },
    width: 920,
    height: '100%'
  };

  var chart = new google.visualization.BarChart(document.getElementById('chart_div'));

  // chart ready event
  google.visualization.events.addListener(chart, 'ready', function () {
    // legend container
    var legend = document.getElementById('legend_div');
    legend.innerHTML = '';

    // build legend from chart data
    var colorPallette = [];
    for (var colIndex = 0; colIndex < data.getNumberOfColumns(); colIndex++) {
      // determine if style column
      if (data.getColumnRole(colIndex) === 'style') {
        // save colors for entire series (all rows)
        var seriesColors = '';
        for (var rowIndex = 0; rowIndex < data.getNumberOfRows(); rowIndex++) {
          seriesColors += renderTemplate('template-legend-entry-color', {
            color: data.getValue(rowIndex, colIndex)
          });
        }

        // add legend for series (all colors)
        legend.insertAdjacentHTML('beforeEnd', renderTemplate('template-legend-entry', {
          colors: seriesColors,
          index: colIndex - 1,
          label: data.getColumnLabel(colIndex - 1)
        }));
      }
    }

    // add click event to legend entries
    var legendEntries = legend.getElementsByClassName('legend-entry');
    Array.prototype.forEach.call(legendEntries, function(entry) {
      entry.addEventListener('click', function (e) {
        // find legend entry
        var entry = e.target || e.srcElement;
        if (entry.className.toLowerCase() !== 'legend-entry') {
          entry = entry.parentNode;
        }

        // get data table column index from legend entry
        var columnIndex = parseInt(entry.getAttribute('data-columnIndex'));

        // display legend entry that was clicked
        document.getElementById('message_div').innerHTML = 'legend entry clicked = ' + data.getColumnLabel(columnIndex);

        // select chart series
        chart.setSelection([{row: null, column: columnIndex}]);
      }, false);
    });
  });

  // render html template
  function renderTemplate(templateId, templateProps) {
    var content = document.getElementById(templateId).innerHTML;
    for (var handle in templateProps) {
      if (templateProps.hasOwnProperty(handle)) {
        content = content.replace('{{' + handle + '}}', templateProps[handle]);
      }
    }
    return content.trim();
  }

  // draw chart
  chart.draw(data, options);
});
#legend_div {
  font-family: Arial;
  font-size: 11px;
  text-align: center;
  width: 920px;
}

.legend-entry {
  display: inline-block;
  padding: 16px 4px 8px 4px;
}

.legend-entry-color {
  display: inline-block;
  height: 12px;
  width: 12px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
<div id="legend_div"></div>
<div id="message_div"></div>

<script id="template-legend-entry" type="text/html">
  <div class="legend-entry" data-columnIndex="{{index}}">
    {{colors}}
    <span>{{label}}</span>
  </div>
</script>

<script id="template-legend-entry-color" type="text/html">
  <div class="legend-entry-color" style="background-color: {{color}}"></div>
</script>
Eicher answered 16/2, 2022 at 17:58 Comment(1)
It's definitely what i found. I have had more motivate to digging deeper. Many thanks for spending times.Coppery

© 2022 - 2024 — McMap. All rights reserved.