Search code examples
javascriptd3.jspie-chart

Label text of pie chart not appearing


The labels on my pie chart are not visible, whatever I try (resetting radius, changing text color). The pie chart itself is visible. I have looked at many examples, such as https://bl.ocks.org/santi698/f3685ca8a1a7f5be1967f39f367437c0, but to no avail. There must be something simple that I'm missing, probably in the centroid function. Any help would be appreciated! Code is as follows. It is part of a jinja template, but I guess that's not relevant. Obviously the arcs.append("text") statement is the one that has a mistake somewhere.

<svg width="960" height="500">
</svg>
<script>
    var svg = d3.select("svg");

    var margin = 50,
        width = +svg.attr("width") - margin,
        height = +svg.attr("height") - margin,
        radius = height / 2;

    var g = svg.append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    data = [{fruit: "apple", amount: 3},
            {fruit: "pear", amount: 2},
            {fruit: "kiwi", amount: 5}];
    console.log(data);

    var colors = ['green', 'red', 'blue'];

    var arc = d3.arc()
        .outerRadius(radius - 10)
        .innerRadius(0);

    var labelArc = d3.arc()
        .outerRadius(radius - 40)
        .innerRadius(radius - 40);

    var pie = d3.pie()
        .value(function(d) { return d.amount; });
    console.log(pie(data))

    var arcs = g.selectAll("arc")
        .data(pie(data))
        .enter()
        .append("g")
            .attr("class", "arc");

    arcs.append("path")
        .attr("d", arc)
        .style('fill', function(d, i) {
            return colors[i];
        });

    arcs.append("text")
        .attr("transform", function(d) {
            return "translate(" + labelArc.centroid(d) + ")";
        })
        .text(function(d) {
            return d.fruit;
        });
</script>

Solution

  • D3 pie generator returns an array of objects with several created properties, among them:

    data - the input datum; the corresponding element in the input data array.

    Therefore, it should be:

    .text(function(d) {
        return d.data.fruit;
    });
    

    Here is your code with that change:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
    <svg width="960" height="500">
    </svg>
    <script>
      var svg = d3.select("svg");
    
      var margin = 50,
        width = +svg.attr("width") - margin,
        height = +svg.attr("height") - margin,
        radius = height / 2;
    
      var g = svg.append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
      data = [{
          fruit: "apple",
          amount: 3
        },
        {
          fruit: "pear",
          amount: 2
        },
        {
          fruit: "kiwi",
          amount: 5
        }
      ];
    
      var colors = ['green', 'red', 'blue'];
    
      var arc = d3.arc()
        .outerRadius(radius - 10)
        .innerRadius(0);
    
      var labelArc = d3.arc()
        .outerRadius(radius - 40)
        .innerRadius(radius - 40);
    
      var pie = d3.pie()
        .value(function(d) {
          return d.amount;
        });
    
      var arcs = g.selectAll("arc")
        .data(pie(data))
        .enter()
        .append("g")
        .attr("class", "arc");
    
      arcs.append("path")
        .attr("d", arc)
        .style('fill', function(d, i) {
          return colors[i];
        });
    
      arcs.append("text")
        .attr("transform", function(d) {
          return "translate(" + labelArc.centroid(d) + ")";
        })
        .text(function(d) {
          return d.data.fruit;
        });
    </script>