Home > OS >  How to get data labels to show in D3 stacked bar chart?
How to get data labels to show in D3 stacked bar chart?

Time:11-28

I'm trying to get data labels to show inside of each bar of my stacked bar chart. When I view source, I can see the <text> elements in each bar with the correct number, but they aren't visible in the bar itself

<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<div id="legend"></div>
<style>
</style>
<script>
// set the dimensions and margins of the graph
var margin = { top: 10, right: 30, bottom: 20, left: 50 },
    width = 460 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
    .append("svg")
    .attr("width", width   margin.left   margin.right)
    .attr("height", height   margin.top   margin.bottom)
    .append("g")
    .attr("transform",
        "translate("   margin.left   ","   margin.top   ")");

// Parse the Data
d3.csv("https://raw.githubusercontent.com/JakeRatliff/dh-valve-data/main/Valves Data - Sheet1.csv", function(data) {

    // List of subgroups = header of the csv files = soil condition here
    var subgroups = data.columns.slice(1)
    subgroups.pop()
    console.log(subgroups)

    // List of groups = species here = value of the first column called group -> I show them on the X axis
    var groups = d3.map(data, function(d) { return (d.Year) }).keys()
    console.log(groups)

    // Add X axis
    var x = d3.scaleBand()
        .domain(groups)
        .range([0, width])
        .padding([0.2])
    svg.append("g")
        .attr("transform", "translate(0,"   height   ")")
        .call(d3.axisBottom(x).tickSizeOuter(0));

    // Add Y axis
    var y = d3.scaleLinear()
        //.domain([0, 60])
        .domain([0, d3.max(data, function(d) { return  d.Total; })])
        .range([height, 0]);
    svg.append("g")
        .call(d3.axisLeft(y));

    // color palette = one color per subgroup
    var color = d3.scaleOrdinal()
        .domain(subgroups)
        .range(['#00539B', '#E0750B'])

    //stack the data? --> stack per subgroup
    var stackedData = d3.stack()
        .keys(subgroups)
        (data)

    // Show the bars
    svg.append("g")
        .selectAll("g")
        // Enter in the stack data = loop key per key = group per group
        .data(stackedData)
        .enter().append("g")
        .attr("fill", function(d) { return color(d.key); })
        .selectAll("rect")
        // enter a second time = loop subgroup per subgroup to add all rectangles
        .data(function(d) { return d; })
        .enter().append("rect")
        .attr("x", function(d) { return x(d.data.Year); })
        .attr("y", function(d) { return y(d[1]); })
        .attr("height", function(d) { return y(d[0]) - y(d[1]); })
        .attr("width", x.bandwidth())
        .attr("class", "bar")

        .append("text")
        .attr("x", function(d) { return x(d.data.Year); })
        .attr("y", function(d) { return y(d[1]); })
        .text(function(d) { return d[1] })


})
</script>

Here is a codepen if that is preferred: https://codepen.io/jake2134/pen/QWMQJOB

Thanks in advance for any help. I've Google around but the results seem to be outdated.

CodePudding user response:

Use a variable to create a group, then append twice to it.

var bar_groups = svg.append("g")
        .selectAll("g")
        // Enter in the stack data = loop key per key = group per group
        .data(stackedData)
        .enter().append("g")
        .attr("fill", function(d) { return color(d.key); })

var bars = bar_groups.selectAll("g")
    // enter a second time = loop subgroup per subgroup to add all rectangles
    .data(function(d) { return d; })
    .enter().append("g")
  
bars.append('rect')
    .attr("x", function(d) { return x(d.data.Year); })
    .attr("y", function(d) { return y(d[1]); })
    .attr("height", function(d) { return y(d[0]) - y(d[1]); })
    .attr("width", x.bandwidth())
    .attr("class", "bar")

bars.append("text")
    .attr("x", function(d) { return x(d.data.Year); })
    .attr("y", function(d) { return y(d[1]); })
    .text(function(d) { return d[1] })
  • Related