Reputation: 401
I am trying to figure out how to show more text on a pie chart using mouseover
than just the data that is bound to the pie. Below is my functional code
function Pie(value,names){
svg.selectAll("g.arc").remove()
var outerRadius = 100;
var innerRadius = 0;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie();
var color = d3.scale.category10();
var arcs = svg.selectAll("g.arc")
.data(pie(value))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(950,80)");
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
.on("mouseover",function(d,i) {
arcs.append("text")
.attr("dy", ".5em")
.style("text-anchor", "middle")
.style("fill", function(d,i){return "black";})
.text(d.data)
})
.on("mouseout", function(d) {
arcs.select("text").remove();
});}
The names
array has the same length as the value
array which is passed to the pie. I really hoped that something like this would work by replacing the above mouseover
.
.on("mouseover",function(d,i) {
arcs.append("text")
.attr("dy", ".5em")
.style("text-anchor", "middle")
.style("fill", function(d,i){return "black";})
.text(function(d,i){return (d.data +" " + names[i]);)
})
But the only thing it does is to show all the elements of the values
array stacked one on top of the other and the last element of the names
array. It seems that i
is always the last index in this case. How would I go about that? Could I show the text I want in another way? Thank you in advance.
Upvotes: 1
Views: 4421
Reputation: 108512
First, the variable arcs
is a data-bound d3 selection which represents all the arcs of the pie. So, by calling arcs.append
, you are going to append a text
element for each piece of your pie chart. I think you mean to only append one text
element based on what you moused-over so re-write that as:
svg.append('text')
...
Second, in this expression:
.text(function(d,i){return (d.data +" " + names[i]);)
d
and i
in the mouseover function already represent the data and index of the pie slice being moused over. There is no reason to wrap this in another function and should be re-written:
.text(d.data +" " + names[i]);
Here's a complete example:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.arc path {
stroke: #fff;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.category10();
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var data = [{
value: Math.random(),
}, {
value: Math.random(),
}, {
value: Math.random(),
}, {
value: Math.random(),
}, {
value: Math.random(),
}]
var names = ["A","B","C","D","E"];
var arcs = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.style("fill", function(d,i) {
return color(i);
})
.on("mouseover", function(d, i) {
console.log(d);
svg.append("text")
.attr("dy", ".5em")
.style("text-anchor", "middle")
.style("font-size", 45)
.attr("class","label")
.style("fill", function(d,i){return "black";})
.text(names[i]);
})
.on("mouseout", function(d) {
svg.select(".label").remove();
});
</script>
</body>
</html>
Upvotes: 3