4

A call like

chart.draw(data, { colors: ['#e0440e', '#e6693e', '#ec8f6e', ...], ... });

creates a chart with colors looking like semi-transparent. However, we passed RGB colors, with no alpha parameter!

In other chart apps (like jqPlot, CanvasJS etc) you may pass rgba calls instead, like in

[ 'rgba(255,0,0,0.5)', 'rgba(0,255,0,0.5)', ...]

Google Charts does not seem to support this. But is there any other way to pass RGBA custom colors instead, with a simple syntax?

PS: there is a somehow similar question for pie charts, but mine is different, for custom color palettes.

WhiteHat
  • 59,912
  • 7
  • 51
  • 133
Cristian Scutaru
  • 1,375
  • 19
  • 23
  • 1
    I was wondering the same thing, I believe the only way possible is to write JavaScript that manipulates SVG. – zer00ne Oct 27 '16 at 03:29
  • 1
    For [bar chars](https://developers.google.com/chart/interactive/docs/gallery/columnchart), you can provide `dataOpacity` property that is documented to set opacity for all series. What is not documented is that it can be provided on per-series basis, inside the `series: ` element, and then it will control transparency all data points in a single series. As for individual data points in a series, there is [`fill-opacity` property](https://developers.google.com/chart/interactive/docs/gallery/columnchart?#column-styles) that can be provided from a `{role: "style"}` data column. – GSerg Apr 26 '20 at 19:05

2 Answers2

3

once the 'ready' event fires on the chart, you can modify the svg

just need a way to find the chart elements you want to modify

in the following working snippet, random colors are used to feed the chart

then when 'ready' fires, those colors are found and replaced with rgba

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

function drawChart() {
  var data = google.visualization.arrayToDataTable([
    ['Year', 'Y1', 'Y2'],
    ['2010', 10, 14],
    ['2020', 14, 22],
    ['2030', 16, 24],
    ['2040', 22, 30],
    ['2050', 28, 36]
  ]);

  var seriesColors = ['#00ffff', '#ff00ff'];
  var rgbaMap = {
    '#00ffff': 'rgba(0,255,0,0.5)',
    '#ff00ff': 'rgba(255,0,0,0.5)'
  };

  var options = {
    colors: seriesColors,
  };

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

  // modify svg
  google.visualization.events.addListener(chart, 'ready', function () {
    Array.prototype.forEach.call(chartDiv.getElementsByTagName('rect'), function(rect) {
      if (seriesColors.indexOf(rect.getAttribute('fill')) > -1) {
        rect.setAttribute('fill', rgbaMap[rect.getAttribute('fill')]);
      }
    });
  });

  chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
WhiteHat
  • 59,912
  • 7
  • 51
  • 133
  • great solution! To make it more generic (to work with a pie as well), I processed all elems with a fill attribute within the svg tag: jQuery syntax: $("svg").find("*[fill]").each(...). – Cristian Scutaru Oct 27 '16 at 16:22
  • that works too -- just fyi: use HEX values to feed chart instead of color _names_, such as `'red', 'black'` -- the chart will change `fill` value to HEX equivalent anyway (`'#ff0000', '#000000'`) -- which could cause lookup to fail... – WhiteHat Oct 27 '16 at 16:31
  • we should always use web color values in hex, or rgba when extended with opacity. I think it's bad practice and hard to maintain to mix it up with color names or 3-digit notation (as in #fa0 for #ffaa00). Some other important remark: all hex values should be in lower case, otherwise the code won't work! This is because all fill values such as #FFAA00 are automatically translated into #ffaa00. – Cristian Scutaru Oct 27 '16 at 16:48
0

Use $.attr('opacity', value) for all elements filtered by colors. exapmle with jQuery...

var options = {
  colors: ['#ff5722', '#1976D2', '#2196f3', '#BBDEFB', '#BDBDBD']
  },
  conteiner = $('div'),
  data = {},//some data
  chart = new
google.visualization.PieChart(conteiner);

google.visualization.events.addListener(chart, 'ready', function () {
    chartSetColorOpacity(conteiner, 0.8, options.colors);
});

google.visualization.events.addListener(chart, 'onmouseout', function () {
    chartSetColorOpacity(conteiner, 0.8, options.colors);
});

google.visualization.events.addListener(chart, 'onmouseover', function (target) {
    chartSetColorOpacity(conteiner, 0.8, options.colors);
});

google.visualization.events.addListener(chart, 'select', function (target) {
    chartSetColorOpacity(conteiner, 0.8, options.colors);
});

chart.draw(data, options);
        
function chartSetColorOpacity($container, opacity, matchColors){

    $container = $($container);

    if(!$container.is('svg')){
        $container = $container.find('svg');
    }

    if(typeof opacity === "number"){
        opacity = String(opacity);
    }else if(typeof opacity !== "string"){
        throw new Error('function chartSetColorOpacity(): opacity is not correct! opacity=' + opacity);
    }

    if(matchColors){
        if(typeof matchColors === "string") {
            matchColors = [matchColors];
        }
    }else {
        matchColors = false;
    }

    $container.find('*[fill]:not(opacity)').each(function(indx, element){

        var $this = $(this);

        if(matchColors !== false) {

            var matched = false,
                color = $this.attr('fill').toUpperCase();

            for (var i = matchColors.length - 1; i >= 0; i--) {
                if (matchColors[i].toUpperCase() == color) {
                    matched = true;
                    break;
                }
            }

            if (!matched) return;

        }

        $this.attr('opacity', opacity);

    });

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>