Timothy Martin
Timothy Martin

Reputation: 76

Dimple Stacked Bar Chart - adding label for aggregate total

I'm trying to add a label to the aggregate total for a stacked bar chart above each bar. I used this example (http://dimplejs.org/advanced_examples_viewer.html?id=advanced_bar_labels) to add the totals for each section of the bar, but I'm not sure how to add the total above. I've also been able to add total labels above each bar for a single series (not stacked). I just can't get it to work with a stacked bar chart.

My current workaround is plotting an additional null series line, but making the line and markers transparent so you can still see the total value in the tooltip. However, I'd really like to just have the totals displayed above each bar.

Here's the code:

var svg = dimple.newSvg("#chartContainer", 590, 400);
var myChart = new dimple.chart(svg, data);
myChart.setBounds(80, 30, 510, 305);
var x = myChart.addCategoryAxis("x", "Month");
x.addOrderRule(Date);
var y = myChart.addMeasureAxis("y", "Calls");
y.showGridlines = true;
y.tickFormat = ',6g';
y.overrideMin = 0;
y.overrideMax = 800000;
var s = myChart.addSeries("Metric", dimple.plot.bar);

s.afterDraw = function (shape, data) {
    var s = d3.select(shape),
        rect = {
            x: parseFloat(s.attr("x")),
            y: parseFloat(s.attr("y")),
            width: parseFloat(s.attr("width")),
            height: parseFloat(s.attr("height"))
        };
    if (rect.height >= 1) {
        svg.append("text")
            .attr("x", rect.x + rect.width / 2)
            .attr("y", rect.y + rect.height / 2 + 3.5)
            .style("text-anchor", "middle")
            .style("font-size", "9px")
            .style("font-family", "sans-serif")
            .style("opacity", 0.8)
            .text(d3.format(",.1f")(data.yValue / 1000) + "k");
    }
};

myChart.addLegend(60, 10, 510, 20, "right");
myChart.draw();

Here is the JSFiddle: http://jsfiddle.net/timothymartin76/fusaqyhk/16/

I appreciate any assistance on this.

Thanks!

Upvotes: 1

Views: 1105

Answers (1)

John Kiernander
John Kiernander

Reputation: 4904

You can add them after drawing by calculating the bar totals and deriving the y position from that:

// Iterate every value on the x axis
x.shapes.selectAll("text").each(function (d) {

    // There is a dummy empty string value on the end which we want to ignore
    if (d && d.length) {

        // Get the total y value
        var total = d3.sum(data, function (t) { return (t.Month === d ? t.Calls : 0); });
        // Add the text for the label
        var label = svg.append("text");

        // Set the x position
        // x._scale(d) is the tick position of each element
        // (myChart._widthPixels() / x._max) / 2 is half of the space allocated to each element
        label.attr("x", x._scale(d) + (myChart._widthPixels() / x._max) / 2)

        // Vertically center the text on the point
        label.attr("dy", "0.35em")

        // Style the text - this can be better done with label.attr("class", "my-label-class")
        label.style("text-anchor", "middle")
            .style("font-size", "9px")
            .style("font-family", "sans-serif")
            .style("opacity", 0.8)

        // Set the text itself in thousands
        label.text(d3.format(",.1f")(total / 1000) + "k");

        // Once the style and the text is set we can set the y position
        // y._scale(total) gives the y position of the total (and therefore the top of the top segment)
        // label.node().getBBox().height gives the height of the text to leave a gap above the bar
        label.attr("y", y._scale(total) - label.node().getBBox().height)
    }

});

Here is your updated fiddle: http://jsfiddle.net/fusaqyhk/17/

Upvotes: 1

Related Questions