Matthias
Matthias

Reputation: 37

Google chart stacked bar chart two positive scale

I'm currently working on a chart using google chart api, but i struggle at making a twice positive horizontal scale. Like : 50 25 0 25 50 with a stacked chart bar centered on the '0' in the scale. I kind of got it centered using a "dummy" invisible bar to push everything, but i can't find a way to get the horizontal axis label customized without editing the windowsview.

here's my actual code :

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

function findMax(arr) {
    var max = 0;
    for (var n in arr) {
    if (n > 0) {
        var cMax = arr[n][2];
      if (cMax > max)
        max = cMax
    }
  }
  return (max);
}

function findLine(arr) {
    var max = 0;
    for (var n in arr) {
    if (n > 0) {
        var cMax = arr[n][2] + arr[n][3] + arr[n][4];
      if (cMax > max)
        max = cMax
    }
  }
  return (max / 2);
}

function space(arr, maxL) {
  var max = findMax(arr);
  for (var n in arr) {
    if (n > 0) {
        arr[n][1] = max - arr[n][2] + (maxL);
    }
  }
}

function drawAnnotations() {
    var raw_data = [];
    raw_data.push( ['Compétence', 'invisible', 'Expert', 'Certifié', 'Non certifié'] );
    raw_data.push( ['Java', 0, 24, 31, 12] );
    raw_data.push( ['PHP', 0, 17, 22, 10] );
    raw_data.push( ['JavaScript', 0, 6, 10, 22] );
    raw_data.push( ['Cpp', 0, 0, 0, 50] );
    raw_data.push( ['C#', 0, 5, 10, 15] );

    var maxL = findLine(raw_data);
    space(raw_data, maxL);
    var data = google.visualization.arrayToDataTable(raw_data);

    var options = {
      isStacked: true,
      enableInteractivity: false,
      width: 600, height: 400,
      legend : 'none',
      bar: { groupWidth: '85%' },
      colors: ['ffffff','gray', 'yellow', 'red'], 
      hAxis: {
        title: '',
        baselineColor: '#fff',
        gridlineColor: '#fff'
      },
      vAxis: {
        title: '',
        baselineColor: '#fff',
        gridlineColor: '#fff'
      }
    };
    var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
    chart.draw(data, options);
}

JSfiddle Link

Currently i got what i want exept for the horizontal scale which is not set as i wish it to be. (I tried to use multiple axes but it has proven to be unseccessfull).

edit: I add a link to an image of what kind of chart (scale) i'm looking to do.


UPDATE

I kinda got it working now :

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
   <meta charset=utf-8 />

    <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawAnnotations);

      function drawAnnotations() {
        var raw_data = [];
        raw_data.push( ['Compétence', 'Expert', 'Certifié', 'Non certifié'] );
        raw_data.push( ['Java', -24, 45, 12] );
        raw_data.push( ['PHP', -17, 22, 10] );
        raw_data.push( ['JavaScript', -6, 10, 22] );
        raw_data.push( ['Cpp', -0, 0, 50] );
        raw_data.push( ['C#', -5, 10, 15] );
        var data = google.visualization.arrayToDataTable(raw_data);

        var options = {
          isStacked: true,
          width: $(window).width() * 0.8, height: 400,
          legend : 'none',
          bar: { groupWidth: '85%' },
          colors: ['gray', 'yellow', 'red'], 
          interpolateNulls: true,
          hAxis: {
            title: 'Number',
            gridlines: {
              color: 'transparent'
            }
          }
        };
        var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }

      $(window).load(function() {
          $('text').each(function(i, el) {
            if ($(this).text()[0] == '-')
             $(this).text($(this).text().substr(1));
          });
      });
    </script>
  </head>
  <body>
    <div id="chart_div" style="width: 900px; height: 500px;"></div>
  </body>
</html>

I had to change the google lib i was using :

previously was :

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

and now i'm using :

<script type="text/javascript" src="https://www.google.com/jsapi"></script>

I'm not sure why it change something but without this change $(window).load was unable to reach "text" and i wasn't able to edit it. Now i'm just converting a part of my chart to negative (the one i wanted on the left) and change the "negative" values from the scale using jquery.

There's just one thing left , the tooltip still show the negative value when you point on the "gray" area of the chart.

I still hope it may help someone else who struggle with this particular problem.

Upvotes: 1

Views: 431

Answers (1)

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59338

In fact, instead of modifying axis text via jQuery you could customize it via ticks feature as shown below:

hAxis: {
            ticks: [{ v: -25, f: '25' }, 0, 25, 50, 75]
       }

Regrading customizing tooltip label, you could consider the following solution to display non-negative value:

1) Attach onmouseover event to Google Chart:

google.visualization.events.addListener(chart, 'onmouseover', function (e) {
    setTooltipContent(data, e);
});

2) Override tooltip negative value:

function setTooltipContent(data, e) {
    if (e.row != null && e.column == 1) {
        var val = Math.abs(data.getValue(e.row, 1));
        var tooltipTextLabel = $(".google-visualization-tooltip-item-list li:eq(1) span:eq(1)");
        tooltipTextLabel.text(val.toString());
    }
} 

Complete example

google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawAnnotations);

function drawAnnotations() {
    var raw_data = [];
    raw_data.push(['Compétence', 'Expert', 'Certifié', 'Non certifié']);
    raw_data.push(['Java', -24, 45, 12]);
    raw_data.push(['PHP', -17, 22, 10]);
    raw_data.push(['JavaScript', -6, 10, 22]);
    raw_data.push(['Cpp', -0, 0, 50]);
    raw_data.push(['C#', -5, 10, 15]);
    var data = google.visualization.arrayToDataTable(raw_data);
    
   
    var options = {
        isStacked: true,
        width: $(window).width() * 0.8, height: 400,
        legend: 'none',
        bar: { groupWidth: '85%' },
        colors: ['gray', 'yellow', 'red'],
        interpolateNulls: true,
        tooltip: {isHtml: true},
        hAxis: {
            title: 'Number',
            gridlines: {
                color: 'transparent'
            },
            ticks: [{ v: -25, f: '25' }, 0, 25, 50, 75]
    }
    };
    var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
    chart.draw(data, options);
    google.visualization.events.addListener(chart, 'onmouseover', function (e) {
        setTooltipContent(data, e);
    });
}

function setTooltipContent(data, e) {
    if (e.row != null && e.column == 1) {
        var val = Math.abs(data.getValue(e.row, 1));
        var tooltipTextLabel = $(".google-visualization-tooltip-item-list li:eq(1) span:eq(1)");
        tooltipTextLabel.text(val.toString());
    }
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<div id="chart_div" style="width: 900px; height: 500px;"></div>

JSFiddle

Upvotes: 1

Related Questions