Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Charts offsetting the horizontal axis marker labels

Does anyone know if its possible to offset the markers so they appear between the column of a google chart?

So that it appears like this design mockup...

enter image description here

Instead of the markers being directly inline with the columns like below which is the default behaviour of the google.visualization.ColumnChart api.

enter image description here

I have search through the documention, however cannot find any references to options that would allow for this kind of customisation. Does anyone know if perhaps there is a way of manipulating the layout after it has been rendered? Or if in fact there is an option to do this but I've just overlooked it?

Thanks

like image 316
Ross Anthony Avatar asked Oct 31 '22 00:10

Ross Anthony


1 Answers

The chart is rendered in a <svg> structure containing <g>, <rect>, <text> (and other) elements. The structure differs a lot form chart to chart, and the internal ordering can change if basic chart elements are left out. The horizontal axis elements is rendered as something like

<text text-anchor="middle" x="468.46875" y="343.05" font-family="Arial" font-size="13" stroke="none" stroke-width="0" fill="#222222">12</text>

To get an idea of where to look for those <text> elements in the <svg> structure you can copy the rendered code of the chart to a editor capable of styling code, or use a online code beautifier.

Then simply iterate through the <svg> by using DOM methods such as querySelector, querySelectorAll, getElementsByTagName etc.

See this google.visualization.ColumnChart : enter image description here

By changing the x attribute of each <text> element that belongs to the horizontal axis we can get the labels to appear between the columns :

google.visualization.events.addListener(chart, 'ready', updateAxis);    
function updateAxis() {
  var x,
      svg = document.getElementById('chart').querySelector('svg'),
      g = svg.querySelectorAll('g'),
      chartArea = g[3].querySelectorAll('g'),
      hAxisTexts = chartArea[5].querySelectorAll('text');

  //0-15 labels, the rest belongs to the yAxis
  for (var i=0;i<16;i++) {
    x = parseFloat(hAxisTexts[i].getAttribute('x'));
    if (x>9) {
      x = x-15;
    } else {
      x = x-18;
    }     
    hAxisTexts[i].setAttribute('x', x);       
  }    
}

enter image description here

demo -> http://jsfiddle.net/hrrL45oq/

This is only an example. You will perhaps need to target a different <g> element holding the <text>'s, and how you manipulate x or other attributes of <text> depends of the layout of the chart.

like image 130
davidkonrad Avatar answered Nov 09 '22 08:11

davidkonrad