Search code examples
javascriptchartsgoogle-visualization

How fill area in GoogleCharts AreaChart with gradient color?


With my google Chart I use this options:

chartOptions: {
                hAxis: {
                    title: 'Tasks'
                },
                vAxis: {
                    title: 'Duration'
                },
                animation:{
                    duration: 2000,
                    startup: true
                },
                colors: ['#6f9654']


            }

How Can I change the color of the area under the graph and how can I fill it with a gradient? (I don't want to fill the background of the whole diagramm)

I don't find any docs on google documentation so far. Is it even possible? Is there a trick?

UPDATE: The Result on @whiteHats solution with my adaptations.: enter image description here


Solution

  • no options for gradient fill of the chart area,
    but you can add your own...

    first, add your gradient definition to the html somewhere.
    this element should not be hidden with display: none,
    otherwise, some browsers may ignore it.
    setting the size to zero pixels seems to work.

    <svg style="width:0;height:0;position:absolute;" aria-hidden="true" focusable="false">
      <linearGradient id="my-gradient" x2="1" y2="1">
        <stop offset="0%" stop-color="#447799" />
        <stop offset="50%" stop-color="#224488" />
        <stop offset="100%" stop-color="#112266" />
      </linearGradient>
    </svg>
    

    next, we need to be able to identify the <rect> element that makes up the chart area.
    here, a default background color is used.

    var chartOptions = {
      chartArea: {
          backgroundColor: '#447799'
      },
      ...
    

    then we find the <rect> element with the default background, and set the fill attribute.
    normally, we could set the gradient fill on the chart's 'ready' event,
    but since you're using animation, the gradient will get overridden as the animation occurs.
    we could also set the fill on the chart's 'animationfinish' event,
    but then there would not be a gradient during animation.

    as such, we have to use a MutationObserver, and set the fill every time the svg is mutated (drawn).

    see following working snippet...

    google.charts.load('current', {
      packages:['corechart']
    }).then(function () {
      var dataTable = new google.visualization.DataTable({
        cols: [
          {label: 'x', type: 'number'},
          {label: 'y', type: 'number'}
        ],
        rows: [
          {c:[{v: 0}, {v: 25}]},
          {c:[{v: 5}, {v: 25}]},
          {c:[{v: 10}, {v: 25}]},
          {c:[{v: 15}, {v: 25}]},
          {c:[{v: 20}, {v: 25}]},
          {c:[{v: 25}, {v: 25}]},
          {c:[{v: 30}, {v: 25}]},
          {c:[{v: 40}, {v: 25}]},
          {c:[{v: 45}, {v: 25}]},
          {c:[{v: 50}, {v: 25}]},
          {c:[{v: 55}, {v: 25}]},
          {c:[{v: 60}, {v: 25}]},
          {c:[{v: 65}, {v: 25}]},
          {c:[{v: 70}, {v: 25}]}
        ]
      });
    
      var chartOptions = {
        chartArea: {
            backgroundColor: '#447799'
        },
        height: 600,
        hAxis: {
            title: 'Tasks'
        },
        vAxis: {
            title: 'Duration'
        },
        animation:{
            duration: 2000,
            startup: true
        },
        colors: ['#6f9654']
      };
    
      var container = document.getElementById("chart_div");
      var chart = new google.visualization.AreaChart(container);
    
      google.visualization.events.addListener(chart, 'ready', function () {
        var observer = new MutationObserver(function () {
          container.getElementsByTagName('svg')[0].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
          Array.prototype.forEach.call(container.getElementsByTagName('rect'), function(rect) {
            if (rect.getAttribute('fill') === '#447799') {
              rect.setAttribute('fill', 'url(#my-gradient) #447799');
            }
          });
        });
        observer.observe(container, {
          childList: true,
          subtree: true
        });
      });
    
      chart.draw(dataTable, chartOptions);
    });
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    
    <div id="chart_div"></div>
    
    <svg style="width:0;height:0;position:absolute;" aria-hidden="true" focusable="false">
      <linearGradient id="my-gradient" x2="1" y2="1">
        <stop offset="0%" stop-color="#447799" />
        <stop offset="50%" stop-color="#224488" />
        <stop offset="100%" stop-color="#112266" />
      </linearGradient>
    </svg>