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!
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>