Show values on top of bars in a barChart

Check updated jsfiddle

.renderlet(function(chart){

    var barsData = [];
    var bars = chart.selectAll('.bar').each(function(d) { barsData.push(d); });

    //Remove old values (if found)
    d3.select(bars[0][0].parentNode).select('#inline-labels').remove();
    //Create group for labels 
    var gLabels = d3.select(bars[0][0].parentNode).append('g').attr('id','inline-labels');

    for (var i = bars[0].length - 1; i >= 0; i--) {

        var b = bars[0][i];
        //Only create label if bar height is tall enough
        if (+b.getAttribute('height') < 18) continue;
        
        gLabels
            .append("text")
            .text(barsData[i].data.value)
            .attr('x', +b.getAttribute('x') + (b.getAttribute('width')/2) )
            .attr('y', +b.getAttribute('y') + 15)
            .attr('text-anchor', 'middle')
            .attr('fill', 'white');
    }

})

If you don’t want the labels visible when the bars redraw (for example when bars change after user filters/clicks other chart) you can move the check of old values from de renderlet to the to a preRedraw
listener.

.on("preRedraw", function(chart){

    //Remove old values (if found)
    chart.select('#inline-labels').remove();

})

Alternative

D3-ish way

Demo jsfiddle

.renderlet(function (chart) {
    
    //Check if labels exist
    var gLabels = chart.select(".labels");
    if (gLabels.empty()){
        gLabels = chart.select(".chart-body").append('g').classed('labels', true);
    }
    
    var gLabelsData = gLabels.selectAll("text").data(chart.selectAll(".bar")[0]);
    
    gLabelsData.exit().remove(); //Remove unused elements
    
    gLabelsData.enter().append("text") //Add new elements
    
    gLabelsData
    .attr('text-anchor', 'middle')
    .attr('fill', 'white')
    .text(function(d){
        return d3.select(d).data()[0].data.value
    })
    .attr('x', function(d){ 
        return +d.getAttribute('x') + (d.getAttribute('width')/2); 
    })
    .attr('y', function(d){ return +d.getAttribute('y') + 15; })
    .attr('style', function(d){
        if (+d.getAttribute('height') < 18) return "display:none";
    });
    
})

Leave a Comment