1

I'm trying to adapt the annotation center solution from here: google charts move annotation position to center of stacked chart on my own chart.

I've built a funnel chart based on the hints here: Centered bars on a Google Chart BarChart?

I combined them into a new solution, but I'm unable to get it working with the annotations centered. I tried it but most time it's not exactly centered. Or it's not readable and the annotation on the second bar runs "under" the chart.

That's how it looks now: https://i.stack.imgur.com/VVkEC.png The label on the first bar is not really centered (too far left) and the label on the second bar is somehow missing the beginning. It supposed to say "60 sssss sss".

<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
        var chart;
        var container;
        var barInfoLabels = [['','','',''],
            ['sssss  sss sssss  sss  sssss  sss 80', '60 sssss  sss', '40 sssss  sssssssss  ssssssss  ssssssssssssss', '20 sssss  sssssssss  ssssssss  ssssssssssssss']];

        function initialize()
        {
            container = document.getElementById('chart_div');
            chart = new google.visualization.BarChart(container);
            // Create and populate the data table.
            var data = new google.visualization.DataTable();

            // First key of the inner array is the label ("Benutzer" and "Nothing"), following keys are the values.
            // Every loop with raw_data needs to start at key "1", after the label.
            var raw_data = [['Invisible', 116.5, 7116.5, 7180, 7248],
                ['Visible', 15767, 1767, 1640, 1504]];

            var funnelLevelNames = ["Step1", "Step2", "Step3", "Step4"];

            // Inner arrays here start directly with the color, so can be started with "0" in a loop.
            var colorData = [['white','white','white','white'],
                ['red','blue','yellow','black']];

            data.addColumn('string', 'Funnel Level');
            for (var i = 0; i  < raw_data.length; ++i) {
                data.addColumn('number', raw_data[i][0]);
            }

            // Color column
            data.addColumn({ type: 'string', role: 'style' });

            // Labels on the funnel bars column
            data.addColumn({ type: 'string', role: 'annotation', p: {html: true}});

            // Tooltip Labels
            data.addColumn({type: 'string', role: 'tooltip'});

            data.addRows(funnelLevelNames.length);
            for (var j = 0; j < funnelLevelNames.length; ++j) {
                data.setValue(j, 0, funnelLevelNames[j].toString());
            }

            var totalIndex = 0;
            for (var i = 0; i  < raw_data.length; ++i) {
                for (var j = 1; j  < raw_data[i].length; ++j) {
                    data.setValue(j-1, i+1, raw_data[i][j]);
                }
            }
            totalIndex = i;

            // Color Values
            for (var i = 0; i  < colorData.length; ++i) {
                for (var j = 0; j  < colorData[i].length; ++j) {
                    data.setValue(j, totalIndex+1, colorData[i][j]);
                }
            }

            // Annotation/Label Values
            for (var i = 0; i  < barInfoLabels.length; ++i) {
                for (var j = 0; j  < barInfoLabels[i].length; ++j) {
                    data.setValue(j, totalIndex+2, barInfoLabels[i][j].toString());
                }
            }

            // Tooltip Values
            var tooltipIndex = totalIndex+3;
            for (var i = 0; i  < barInfoLabels.length; ++i) {
                for (var j = 0; j  < barInfoLabels[i].length; ++j) {
                    data.setValue(j, tooltipIndex, barInfoLabels[i][j].toString());
                }
            }

            google.visualization.events.addListener(chart, 'ready', function () {
                var observer = new MutationObserver(moveAnnotations);
                observer.observe(container, {
                    childList: true,
                    subtree: true
                });
            });

            // Create and draw the visualization.
            chart.draw(data,
                {
                    title:"",
                    width: "100%", height: 600,
                    chartArea: {width: '80%', height: '60%', top: '1%', left: '20%'},
                    colors: ['ffffff','blue'],
                    vAxis: {title: ""},
                    hAxis: {title: "", gridlineColor : 'ffffff', textPosition: 'none'},
                    isStacked: true,
                    legend: {position: 'none'},
                    series: {
                        0: { enableInteractivity: false, tooltip: 'none'}, // Disable tooltip for hidden bars (invisible funnel helper bars for centering)
                        1: { } // Show tooltip for funnel bars
                    }
                }
            )
        }

        function moveAnnotations() {
            var chartLayout = chart.getChartLayoutInterface();
            var barBounds;
            var labelBounds;
            var xAdj;

            var labels = container.getElementsByTagName('text');
            var index = 0;

            Array.prototype.forEach.call(labels, function(label) {
                if (label.getAttribute('text-anchor') === 'end' && (barInfoLabels[1].includes(parseInt(label.textContent)) || barInfoLabels[1].includes(label.textContent))) {
                    console.log(label);
                    barBounds = chartLayout.getBoundingBox('bar#1#' + index);
                    if (barBounds != null) {
                        labelBounds = chartLayout.getBoundingBox('annotationtext#1#' + index);
                        xAdj = (barBounds.width / 2) + (parseFloat(label.getAttribute('font-size')) / 2) - 2;
                        label.setAttribute('x', barBounds.left + xAdj);
                    }
                    index++;
                }
            });
        }
</script>
C4rter
  • 11
  • 1
  • the label on the second bar is white, so it blends in with the background... – WhiteHat Sep 02 '19 at 16:23
  • Ah okay, yes that makes sense now. With that in mind, it's also aligned with the label above. But how can I improve the alignment of the annotation. It's too far to the left. I guess it also has to depend on the width of each label? I tried to get the width from the labelBounds (BoundingBox of the annotation text), but that made the whole chart "wonky". Every time I triggered a hover on one of the bars, the annotations were all over the place, so I skipped that idea and relied on the barBounds. But I guess that's not enough for what I want to achieve. – C4rter Sep 02 '19 at 18:07

0 Answers0