How do I increase the inner radius of a specific arc segment? - javascript

I have a pie chart and I want to increase the inner radius of the arc the user mouses over.
For example, if I mouse over the arc with 161, I want only the inner radius of that arc segment to increase.
How would I do this?
// arc radius
var radius = 200;
var p = Math.PI *2; //full circle
var data = [11,12,51,21,31,58,41,13,14,31,71,31,51,71,16,41,31,161];
var data1 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18];
var width = 1000;
var height = 1000;
//========== color scale ==========//
var colorScale = d3.scale.ordinal()
.range(['#FFEBEB', '#FFC2C2', '#FFADAD', '#FF9999', '#FF7070', '#FF5C5C', '#FF4747',
'#FF1F1F', '#FF0A0A', '#F50000', '#CC0000', '#A30000', '#8F0000', '#660000', '#520000', '#3D0000', '#290000', '#140000']);
//========== Create canvas and arc ==========//
var canvas = d3.select("body")
.append("svg")
.attr("height", height)
.attr("width", width);
var group = canvas.append("g")
.attr("transform", "translate(" + width/2 + ",500)");
var arc = d3.svg.arc()
.innerRadius(radius-50)
.outerRadius(radius);
var pie = d3.layout.pie()
.value(function (d){return d;});
var sorted = data.sort(function(a,b){return a-b});
var arcs = group.selectAll(".arc")
.data(pie(sorted))
.enter()
.append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.style('stroke', 'white')
.style('stroke-width', 2)
.attr("fill", function(d, i){return colorScale(d.data);});
arcs.append("text")
.attr("transform", function(d){
return "translate(" + arc.centroid(d) +")";
})
.attr("text-anchor", "middle")
.text(function(d){return d.data});
//======== mouse over/out =========//
var prevColor;
arcs.on("mouseover", function(d){
prevColor = d3.select(this).select("path").attr("fill");
d3.select(this).select("path")
.attr("fill", "black");
})
.on("mouseout", function(d){
d3.select(this).select("path")
.attr("fill", prevColor);
});
http://jsfiddle.net/64vFq/

If I understand you correctly, it looks like you can just change this line:
var arc = d3.svg.arc()
.innerRadius(radius-50)
.outerRadius(radius);
I changed it to this and it produced a decent result:
var arc = d3.svg.arc()
.innerRadius(radius-150)
.outerRadius(radius);
(increase the 50 to make the part the user can mouse over larger; decrease it for the opposite effect)

I found a solution that seems to work pretty well.
All you need to do is create another arc (a bigger one)
var biggerArc = d3.svg.arc().outerRadius(radius+10).innerRadius(radius - 40);
then add it to your mouseover
arcs.on("mouseover", function (d) {
prevColor = d3.select(this).select("path").attr("fill");
d3.select(this).select("path").attr("fill", "black");
d3.select(this).select("path").transition()
.duration(100)
.attr("d", biggerArc);
}).on("mouseout", function (d) {
d3.select(this).select("path").attr("fill", prevColor);
d3.select(this).select("path").transition()
.duration(100)
.attr("d", arc);
});

Related

D3 pie chart doesnot showing the color

My code is like this. Can you say what is the error? My color is not showing properly although the section text is showing. the data set is the death rate of the US over time.
function clicked(d,i) {
var dataset = [d.females, d.males];
var pcolor = ["green", "pink"];
var outerRadius = 60;
var innerRadius = 0;
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.pie();
//Easy colors accessible via a 10-step ordinal scale
//var color = d3.scaleOrdinal(d3.schemeCategory10);
//Set up groups
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arcs")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
//Draw arc paths
arcs.append("path")
.attr("d", arc)
.attr("fill", function(d, i) {
console.log(d);
return pcolor(i);
});
//Labels
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.value;
});
}

Adding more text to d3 pie chart on mouseover event

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

SVG Adding radial gradient to donut chart

I'm drawing charts with d3.js.
Is it possible to add radial gradients to donut chart, how on this picture?
Assuming the arc parts are path elements that are filled you can use a radial gradient to get that result.
See this similar question, we can reuse the example to arrive at:
var dataset = {
apples: [53245, 28479, 19697, 24037, 40245],
};
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var grads = svg.append("defs").selectAll("radialGradient").data(pie(dataset.apples))
.enter().append("radialGradient")
.attr("gradientUnits", "userSpaceOnUse")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", "100%")
.attr("id", function(d, i) { return "grad" + i; });
grads.append("stop").attr("offset", "15%").style("stop-color", function(d, i) { return color(i); });
grads.append("stop").attr("offset", "20%").style("stop-color", "white");
grads.append("stop").attr("offset", "27%").style("stop-color", function(d, i) { return color(i); });
var path = svg.selectAll("path")
.data(pie(dataset.apples))
.enter().append("path")
.attr("fill", function(d, i) { return "url(#grad" + i + ")"; })
.attr("d", arc);
Jsfiddle: http://jsfiddle.net/X8hfm/

d3.js transition of donuts created by multi-arcs doesn't work

I have created a donut using multi-arcs and I want to update my donut with new data(arcs).
var width = 300;
var height = 300;
var p = Math.PI * 2;
var vis = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var group = vis.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var arcs = [];
arcs[0] = d3.svg.arc()
.innerRadius(50)
.outerRadius(70)
.startAngle(0)
.endAngle(p - 2);
arcs[1] = d3.svg.arc()
.innerRadius(50)
.outerRadius(70)
.startAngle(p - 2)
.endAngle(p);
group.append("path")
.attr("d", arcs[0])
.attr("class", "first")
.attr("fill", "green");
group.append("path")
.attr("d", arcs[1])
.attr("class", "second")
.attr("fill", "grey");
The new data(arcs - functions) must be in arrays and I have to pass them using the .data(dataset) method.
// New data
var data1 = [];
data1[0] = d3.svg.arc()
.innerRadius(60)
.outerRadius(100)
.startAngle(0)
.endAngle(p - 1);
var data2 = [];
data2[0] = d3.svg.arc()
.innerRadius(60)
.outerRadius(100)
.startAngle(p - 1)
.endAngle(p);
-I can update my donut with the new arcs but the issue that I have is that the transition doesn't work.
-I want just to make the transition work following the steps that I described before.
I know already that if i don't use the .data(dataset) method and I use the .attr("d", arc) instead of .attrTween method then the transition will work.
-However that is not what I want because I want to apply the solution to multi-donuts.
//On click, update with new data
d3.select("p")
.on("click", function () {
//Update all rects
vis.selectAll("path.first")
.data(data1)
.transition()
.duration(1000)
.attrTween("d", function (d) { return d; });
vis.selectAll("path.second")
.data(data2)
.transition()
.duration(1000)
.attrTween("d", function (d) { return d; });
Here is an example, click update to see the changes: example

D3 Donut chart: Display Value on segment hover

Long time lurker 1st time poster. I am trying to display the text value form a CSV file when the relevant segment of pie chart is hovered over. I have the pie chart (thanks to Mike Bostock) and the display when hovering but cant remove it on the mouse out. Any help would be greatly appreciated at this stage.
var width = 960,
height = 600,
radius = Math.min(width, height) / 2.5;
var arc = d3.svg.arc()
.outerRadius(radius + 10)
.innerRadius(radius - 70);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var color = d3.scale.ordinal()
.range(["#0bd0d2", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.Total; });
var pieSlice = svg.selectAll("g.slice");
d3.csv("childcare.csv", function(error, data) {
data.forEach(function(d) {
d.population = +d.population;
});
var arcs = svg.selectAll("g.slice")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
arcs.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.place); })
.on("mouseenter", function(d) {
//console.log("mousein")
arcs.append("text")
.attr("transform", arc.centroid(d))
.attr("dy", ".5em")
.style("text-anchor", "middle")
.style("fill", "blue")
.attr("class", "on")
.text(d.data.place);
})
.on("mouseout", function(d) {
console.log("mouseout")
});
});
You can just save your text and remove it on mouseout:
var text;
var arcs = svg.selectAll("g.slice")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
arcs.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.place); })
.on("mouseenter", function(d) {
//console.log("mousein")
text = arcs.append("text")
.attr("transform", arc.centroid(d))
.attr("dy", ".5em")
.style("text-anchor", "middle")
.style("fill", "blue")
.attr("class", "on")
.text(d.data.place);
})
.on("mouseout", function(d) {
text.remove();
});

Categories