1
votes

I am creating a horizontal bar chart using Google charts and I want to position the horizontal axis tick labels between ticks (offset tick label to the right by half a tick). There is also no guarantee that each label will be the same number of characters. Is there any functionality to achieve this?

This is my function for creating the chart

function drawChart() {
            var data = google.visualization.arrayToDataTable([
                ["Performance", "Level", { role: "style" }],
                ["PL", 1.01, "#5aa66d"]
            ]);

            var view = new google.visualization.DataView(data);
            view.setColumns([0, 1,
                {
                    calc: function (dt, rowIndex) { return 'PL=' + (dt.getValue(rowIndex, 1)).toString()} ,
                    sourceColumn: 1,
                    type: "string",
                    role: "annotation"
                },
                2]);

            var options = {
                width: 600,
                height: 100,
                bar: { groupWidth: "80%" },
                legend: { position: "none" },
                hAxis: {
                    minValue: 0,
                    maxValue: 3,
                    ticks: [
                        { v: 0, f: 'Col1' },
                        { v: 1, f: 'Col2' },
                        { v: 2, f: 'Col3' },
                        { v: 3, f: 'Col4' }
                    ]
                }
            };
            var chart = new google.visualization.BarChart(document.getElementById("barchart_values"));
            chart.draw(view, options);
        }

This is the chart currently https://imgur.com/LvQEbtY and this is what I want to achieve: https://imgur.com/hwvIOG2

EDIT: For ideas, right before chart.draw I add an event listener and find all the text tags and modify the 'x' attribute to re-position the tick labels. This works, but it also affects the on-bar data label which is a problem.

google.visualization.events.addListener(chart, 'ready', function () {
       var elements = document.getElementById("barchart_values").getElementsByTagName("text");
       for (var i = 0; i < elements.length; i++) {
              elements[i].setAttribute('x', (Number(elements[i].getAttribute('x')) + (chart.getChartLayoutInterface().getBoundingBox('chartarea').width / 4 / 2))); //chart width / tick count / 2
                }
            });
1
@WhiteHat I don't think the answer you provided works in my case as the '0' tick label is still on the horiztonal axis when it should be shifted up half a tick. - Ryan Gray

1 Answers

0
votes

first, we won't be able to offset the grid lines and use the ticks option.

let's offset the grid lines by making the major transparent and the minor visible.
we can also offset the baseline by setting to a negative value.

        baseline: -0.5,
        minorGridlines: {
            color: '#cccccc',
            count: 1
        },
        gridlines: {
            color: 'transparent',
            count: 4
        },

then, in order to have custom tick labels, we can use your original idea to change them manually.
just need a unique attribute to separate them from the bar labels.
here, the text-anchor attribute is used.

        if (elements[i].getAttribute('text-anchor') === 'middle') {
            elements[i].textContent = 'Col' + parseInt(elements[i].textContent) + 1;
        }

see following working snippet...

google.charts.load('current', {
  packages:['corechart']
}).then(function () {
    var data = google.visualization.arrayToDataTable([
        ["Performance", "Level", { role: "style" }],
        ["PL", 1.01, "#5aa66d"]
    ]);

    var view = new google.visualization.DataView(data);
    view.setColumns([0, 1, {
        calc: function (dt, rowIndex) { return 'PL=' + (dt.getValue(rowIndex, 1)).toString()} ,
        sourceColumn: 1,
        type: "string",
        role: "annotation"
    }, 2]);

    var options = {
        width: 600,
        height: 100,
        bar: { groupWidth: "80%" },
        legend: { position: "none" },
        hAxis: {
            baseline: -0.5,
            minorGridlines: {
                color: '#cccccc',
                count: 1
            },
            gridlines: {
                color: 'transparent',
                count: 4
            },
            minValue: 0,
            maxValue: 3,
        }
    };

    var chart = new google.visualization.BarChart(document.getElementById("barchart_values"));

    google.visualization.events.addListener(chart, 'ready', function () {
        var elements = document.getElementById("barchart_values").getElementsByTagName("text");
        for (var i = 0; i < elements.length; i++) {
            if (elements[i].getAttribute('text-anchor') === 'middle') {
                elements[i].textContent = 'Col' + (parseInt(elements[i].textContent) + 1);
            }
        }
    });

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

the above will ensure all the labels remain visible, just simply moving them, could cause them to be pushed off the visible portion of the chart.