Reputation: 103
In the code below, a simple pie chart is created, but I am not able to move one slice towards the outer side of the chart when selected.
I want the individual (element) slice to be positioned outer the pie and the rest of the pie chart elements(slices) in its usual position, something like this:
Here is my code:
<!DOCTYPE html>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data = [35, 20, 45];
var width = 300,
height = 300,
radius = 150;
var arc = d3.arc()
.outerRadius(130);
var arcLabel = d3.arc()
.outerRadius(radius - 30)
.innerRadius(radius - 20);
var pie = d3.pie()
.value(function(d) {
return d;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var emptyPies = svg.selectAll(".arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
emptyPies.append("path")
.attr("d", arc)
.style("fill", function(d, i) {
return color[i];
})
emptyPies.append("text")
.attr("transform", function(d) {
return "translate(" + arcLabel.centroid(d) + ")";
})
.text(function(d) {
return d.data;
});
</script>
Upvotes: 2
Views: 2475
Reputation: 1
A simple solution is to use multiple arc() but to do slice we can use arc.centroid() of 2nd arc. The following code will work in v5.
function onDrawPieChart() {
var data = [35, 20, 45];
var color = d3.schemeCategory10;
var width = 600;
var height = 600;
var radius = 100;
var pie = d3.pie().value((d) => d);
var arc = d3.arc().innerRadius(0).outerRadius(130);
var arc2 = d3.arc().innerRadius(0).outerRadius(20);
var slicedIndex = 1;
var pieData = pie(data);
var centroid = arc2.centroid(pieData[slicedIndex]);
var svg = d3
.select("body")
.append("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height].join(" "))
.attr("width", width)
.attr("height", height)
.append("g");
svg
.selectAll("path")
.data(pieData)
.join("path")
.attr("fill", (d, i) => color[i])
.attr("d", (d) => arc(d))
.attr("transform", (d, i) => {
if (i === slicedIndex) {
var [x, y] = centroid;
return "translate(" + x + ", " + y + ")";
}
});
}
Upvotes: 0
Reputation: 102194
A simple solution is creating a different arc generator:
var arc2 = d3.arc()
.outerRadius(radius)
.innerRadius(60);
And, when setting the "d"
attribute, choosing which arc generator to use. For instance, moving the red slice:
emptyPies.append("path")
.attr("d", function(d,i){
return i != 1 ? arc(d) : arc2(d);
})
Here is your code with that change:
<!DOCTYPE html>
<style>
.arc text {
text-anchor: middle;
}
.arc path {
stroke: white;
}
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data = [35, 20, 45];
var width = 300,
height = 300,
radius = Math.min(width, height) / 2;
var color = ["brown", "red", "blue"];
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(50);
var arc2 = d3.arc()
.outerRadius(radius)
.innerRadius(60);
var arcLabel = d3.arc()
.outerRadius(radius - 30)
.innerRadius(radius - 20);
var pie = d3.pie()
.value(function(d) {
return d;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var emptyPies = svg.selectAll(".arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
emptyPies.append("path")
.attr("d", function(d,i){
return i != 1 ? arc(d) : arc2(d);})
.style("fill", function(d, i) {
return color[i];
})
emptyPies.append("text")
.attr("transform", function(d) {
return "translate(" + arcLabel.centroid(d) + ")";
})
.text(function(d) {
return d.data;
});
</script>
Upvotes: 1