3

I'm trying to create labels outside some arcs. I read this post: Label outside arc (Pie chart) d3.js but still can't make it work. Somehow only one text label appears in the DOM and its location is not correct.

Here is the JSFiddle link: https://jsfiddle.net/SashimiEthan/rLe9g3bq/

Here is my code:

<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="d3.min.js"></script>
</head>
<body>
<script>

  var margin = {top: 10, right: 50, bottom: 10, left: 50},
      width = 300,
      r = width / 2,
      labelr = r + 20,
      outerRadius = 150,
      innerRadius = outerRadius - 30;
      numberOfSegments = 12;
      radians = (Math.PI * 2) / numberOfSegments;
      degrees = 360 / numberOfSegments;

  var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", 530);

  for (var j = 0; j < 5; j++) {
    var arc = d3.svg.arc()
        .innerRadius(innerRadius - j*30)
        .outerRadius(outerRadius - j*30)
        .startAngle(function (d,i) { return radians * i } )
        .endAngle(function (d,i) { return radians * (i + 1) });

    var myGroup = svg.append("g")
        .attr("transform", "translate(200,200)")
        .attr("class","arcgroup")
        .selectAll("path").data(d3.range(numberOfSegments))
        .enter().append("path")     
        .attr("class", "seg"+j+"")
        .attr("d", arc)
        .attr("fill", function(d,i) {
          return d3.hsl(i * degrees, 1 - 0.2*j, 0.5)
        });
  }

  var pos = d3.svg.arc()
      .innerRadius(innerRadius+30)
      .outerRadius(outerRadius+30)
      .startAngle(function (d,i) { return radians * i } )
      .endAngle(function (d,i) { return radians * (i + 1) });

  var label = svg.append("text")
      .attr("transform", function(d,i) { 
        return "translate(" + pos.centroid(d,i) + ")"; 
      })
      .attr("text-anchor", "middle")
      .text(function(d,i){
              return i*degrees + "°";
      });
</script>

</body>
</html>

Many thanks!

Community
  • 1
  • 1
Ethan
  • 37
  • 6
  • Welcome to Stack Overflow! Can you be more specific? When you say the location is not correct, please explain. Where did the label appear? Where did you want it to appear? – Lee Jenkins Nov 10 '15 at 17:17

1 Answers1

2

You're working on the svg without a selection : you're only appending a single element without any datum attached, that's why d=undefined and i=0 in your transform function for example.

Use a selection like you do in your group creations : something like

var selection = svg.append("g").attr("transform", "translate(200,200)").
    selectAll("text").data(d3.range(numberOfSegments)).enter()

var label = selection.append("text")
    .attr("transform", function (d) {
        return "translate(" + pos.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")
    .text(function (d) {
        return d * degrees + "°";
    });

And a demo (the labels' positioning could use some work but that should get you started)

var margin = {
    top: 10,
    right: 50,
    bottom: 10,
    left: 50
},
width = 300,
    r = width / 2,
    labelr = r + 20,
    outerRadius = 150,
    innerRadius = outerRadius - 30;
numberOfSegments = 12;
radians = (Math.PI * 2) / numberOfSegments;
degrees = 360 / numberOfSegments;

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", 530);

for (var j = 0; j < 5; j++) {
    var arc = d3.svg.arc()
        .innerRadius(innerRadius - j * 30)
        .outerRadius(outerRadius - j * 30)
        .startAngle(function (d, i) {
         return radians * i
        }).endAngle(function (d, i) {
            return radians * (i + 1)
        });

    var myGroup = svg.append("g")
        .attr("transform", "translate(200,200)")
        .attr("class", "arcgroup")
        .selectAll("path").data(d3.range(numberOfSegments))
        .enter().append("path")
        .attr("class", "seg" + j + "")
        .attr("d", arc)
        .attr("fill", function (d, i) {
        return d3.hsl(i * degrees, 1 - 0.2 * j, 0.5)
    });
}


var pos = d3.svg.arc()
    .innerRadius(innerRadius+30)
    .outerRadius(outerRadius+30)
    .startAngle(function (d) {
     return radians * d
 }).endAngle(function (d) {
     return radians * (d + 1)
 });


var selection = svg.append("g").attr("transform", "translate(200,200)").
 selectAll("text").data(d3.range(numberOfSegments)).enter()

var label = selection.append("text")
    .attr("transform", function (d) {
     return "translate(" + pos.centroid(d) + ")";
 })
    .attr("text-anchor", "middle")
    .text(function (d) {
     return d * degrees + "°";
 });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
nikoshr
  • 32,926
  • 33
  • 91
  • 105
  • I see! Thank you so so much! Definitely going to make a note of this! – Ethan Nov 10 '15 at 17:44
  • Adding this line will vertically align your text to the center of the text: .attr("alignment-baseline", "central") – Deejers Feb 17 '16 at 15:12