Search code examples
javascripthtmlchartsgoogle-visualizationmutation-observers

google chart change color of individual histogram data points


I have the following code (see codepen) that allows me to change the color of each individual histogram data point after the chart is drawn. It works as intended. However, the colors mess up after the user hovers over the data points. What's going on and how can I fix it?

google.charts.load('current', {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
  var rawData = [
    ['Dinosaur', 'Length', 'color'],
    ['Acrocanthosaurus (top-spined lizard)', 12.2, 'red'],
    ['Albertosaurus (Alberta lizard)', 9.1, 'green'],
    ['Allosaurus (other lizard)', 12.2, 'green'],

  ];

  // sort data by 'Length'
  var data = google.visualization.arrayToDataTable(rawData);
  data.sort([{column: 1}]);

  

  var options = {
    
    title: 'Lengths of dinosaurs, in meters',
    legend: { position: 'none' },
    
  };

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

  google.visualization.events.addListener(chart, 'ready', function () {
    var observer = new MutationObserver(function () {
      var index = 0;
      var item = 1;
      Array.prototype.forEach.call(container.getElementsByTagName('rect'), function (rect) {
        
          if (rect.getAttribute('fill') === '#3366cc') {
            rect.setAttribute('fill', rawData[item][2]);
            item++
          }
          
          index++;
        
      });
    });
    observer.observe(container, {
      childList: true,
      subtree: true
    });
  });

  chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>


Solution

  • in the observer, need to check for all colors...

        switch (rect.getAttribute('fill')) {
          case '#3366cc':
          case 'red':
          case 'green':
            rect.setAttribute('fill', rawData[item][2]);
            item++
            break;
        }
    

    see following working snippet...

    google.charts.load('current', {
      packages:['corechart']
    }).then(function drawChart() {
      var rawData = [
        ['Dinosaur', 'Length', 'color'],
        ['Acrocanthosaurus (top-spined lizard)', 12.2, 'red'],
        ['Albertosaurus (Alberta lizard)', 9.1, 'green'],
        ['Allosaurus (other lizard)', 12.2, 'green'],
      ];
    
      // sort data by 'Length'
      var data = google.visualization.arrayToDataTable(rawData);
      data.sort([{column: 1}]);
    
      var options = {
        title: 'Lengths of dinosaurs, in meters',
        legend: { position: 'none' },
      };
    
      var container = document.getElementById('chart_div');
      var chart = new google.visualization.Histogram(container);
    
      google.visualization.events.addListener(chart, 'ready', function () {
        var observer = new MutationObserver(function () {
          var index = 0;
          var item = 1;
          Array.prototype.forEach.call(container.getElementsByTagName('rect'), function (rect) {
            switch (rect.getAttribute('fill')) {
              case '#3366cc':
              case 'red':
              case 'green':
                rect.setAttribute('fill', rawData[item][2]);
                item++
                break;
            }
            index++;
          });
        });
        observer.observe(container, {
          childList: true,
          subtree: true
        });
      });
    
      chart.draw(data, options);
    });
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="chart_div"></div>