I currently have a simple D3 Chart looking like this.
And what i want simply is to have a range box inside the chart. Basically semi transparent.
Imagine if inside the grey box was semi - transparent.
Source:
<script>
var configuration = {"xtitle":"X"};
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var line2 = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("data.json", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.x = parseDate(d.x);
d.y = d.y;
});
x.domain([data[0].x, data[data.length - 1].x]);
y.domain(d3.extent(data, function(d) { return d.y; }));
var meanx = [{x:parseDate("20111001"),y:25},{x:parseDate("20111002"),y:60},{x:parseDate("20111003"),y:25}];
svg.append("linearGradient")
.attr("id", "temperature-gradient")
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", 0).attr("y1", y(50))
.attr("x2", 0).attr("y2", y(60))
.selectAll("stop")
.data([
{offset: "0%", color: "green"},
{offset: "50%", color: "gray"},
{offset: "100%", color: "red"}
])
.enter().append("stop")
.attr("offset", function(d) { return d.offset; })
.attr("stop-color", function(d) { return d.color; });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text(configuration.xtitle);
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
svg.append("path")
.datum(meanx)
.attr("class", "line")
.attr("d", line);
svg.append('path')
.attr('class', 'area upper outer')
.attr('d', upperOuterArea)
.attr('clip-path', 'url(#rect-clip)');
svg.append("path")
.attr("class","box")
.attr("x1",0).attr("y1",20)
.attr("x2",0).attr("y2",50);
});
</script>
At the very bottom of your script, append a rectangle:
svg.append("rect").attr("x", 0)
.attr("y", y(45))
.attr("width", width)
.attr("height", y(25) - y(45))
.attr("fill", "white")
.attr("opacity", 0.6);
This goes from 45 to 25 in your y axis. The rectangle is white, and its opacity changes the appearance of the lines behind it.
Related
Using "Focus+Context via Brushing" d3js sample i created this chart . Now i need to add a tooltip to it.So i tried the example chart "Using d3-tip to add tooltips to a d3 bar chart" to get an idea. But as u can see in the chart i made,the tool tip does not place correctly. It doesn't move/sticked with the line and i still could not find the issue. Im attaching my code here,
var margin = {top: 10, right: 10, bottom: 100, left: 40},
margin2 = {top: 220, right: 10, bottom: 20, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom,
height2 = 300 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%b %Y").parse;
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.timeStamp); })
.y(function(d) { return y(d.inFlightRequestCount); });
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Flight Request Count:</strong> <span style='color:red'>" + d.inFlightRequestCount +
"</span> <strong>Time:</strong> <span style='color:red'>" + new Date(d.timeStamp) + "</span>";
})
var line2 = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x2(d.timeStamp); })
.y(function(d) { return y2(d.inFlightRequestCount); });
var svg = d3.select("#rowTable1").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
svg.call(tip);
var data = jsonDataFlightRequest;
x.domain(d3.extent(data, function(d) { return d.timeStamp; }));
y.domain([0, d3.max(data, function(d) { return d.inFlightRequestCount; })]);
x.domain(d3.extent(data, function(d) { return d.timeStamp; }));
y.domain([0, d3.max(data, function(d) { return d.inFlightRequestCount; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
svg.selectAll(".line2")
.data(data)
.enter().append("rect")
.attr("class", "line")
.attr("x", function(d) { return x(d.timeStamp); })
.attr("width", 1)
.attr("y", function(d) { return y(d.inFlightRequestCount); })
.attr("height", function(d) { return height - y(d.inFlightRequestCount); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select(".line").attr("d", line);
focus.select(".x.axis").call(xAxis);
}
function type(d) {
d.date = parseDate(d.timeStamp);
d.price = +d.inFlightRequestCount;
return d;
}
Can anyone please help me to overcome this problem.Any help will be really appreciated.
i've a problem with Focus+Context via Brushing (bl.ocks.org/mbostock/1667367#index.html)
That work well when i load it, but when I select the zone to display in main chart, I've nothing in the main chart
Before select area :
http://puu.sh/hdB8a/f112d63d12.png
After select area :
http://puu.sh/hdBa0/c744f6e914.png
the code : (variable data is an array containing object with value and date attribute)
var margin = {top: 10, right: 10, bottom: 100, left: 40},
margin2 = {top: this.h-70, right: 10, bottom: 20, left: 40},
width = this.w - margin.left - margin.right,
height = this.h - margin.top - margin.bottom,
height2 = this.h - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%b %Y").parse;
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(6).tickSize(2),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom").ticks(6).tickSize(2),
yAxis = d3.svg.axis().scale(y).orient("left").tickSize(2);
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var area = d3.svg.area()
.interpolate("basis")
.x(function(d) { return x(new Date(d.date)); })
.y0(height)
.y1(function(d) { return y(d.value); });
var area2 = d3.svg.area()
.interpolate("basis")
.x(function(d) { return x2(new Date(d.date)); })
.y0(height2)
.y1(function(d) { return y2(d.value); });
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("fill","none")
.attr("stroke","#000")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("fill","none")
.attr("stroke","#000")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
data.sort(function(a, b) {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
x.domain(d3.extent(data.map(function(d) { return new Date(d.date); })));
y.domain([d3.min(data.map(function(d) { return d.value; })), d3.max(data.map(function(d) { return d.value; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area)
.attr("clip-path","url(#clip)")
.attr("stroke",chartcolor);
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.attr("stroke","none")
.attr("fill",chartcolor)
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.attr("stroke","none")
.attr("fill",chartcolor)
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2)
.attr("stroke",chartcolor)
.attr("clip-path","url(#clip)");
context.append("g")
.attr("class", "x axis")
.attr("stroke","none")
.attr("fill",chartcolor)
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.attr("stroke","none")
.attr("fill",chartcolor)
.attr("fill-opacity","0.125")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent() );
focus.select(".area").attr("d", area);
focus.select(".x.axis").call(xAxis);
}
Thanks for your help.
EDIT :
I resolve my problem, instead of d3.svg.area(), I use d3.svg.line()
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(new Date(d.date))+margin.left+margin.right; })
.y(function(d) { return y(Number(d.value))+margin.top+margin.bottom; });
var line2 = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x2(new Date(d.date))+margin2.left+margin2.right; })
.y(function(d) { return y2(Number(d.value))+margin2.top+margin2.bottom; });
And line(data) instead of datum(data)
focus.append("path")
.attr("class", "line")
.attr("d", line(data))
.attr("clip-path","url(#clip)")
.attr("stroke",chartcolor);
context.append("path")
.attr("class", "line")
.attr("d", line2(data))
.attr("stroke",chartcolor)
.attr("clip-path","url(#clip)");
Thank you for looking
I just started using D3.js, and have been trying to make this stacked bar chart horizontal(link below).
https://github.com/DeBraid/www.cacheflow.ca/blob/master/styles/js/d3kickchart.js
http://cacheflow.ca/blog/index.html (You can find the chart in the middle of the page)
As a result, I completely stacked on the half way... I would greatly appreciate it if anyone gives me some guides to archive this.
Problem Solved:
I found the way to made the virtical bar chart horizontal. Hope this could help someone who are facing same problem.
Below is the fixed code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
</style>
<body>
<div id="chart-svg"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 50, bottom: 100, left: 75},
width = 740 - margin.left - margin.right,
height = 170 - margin.top - margin.bottom;
var svg = d3.select("#chart-svg").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("mta.csv", function (data){
var headers = ["meeting","construction","management","aa","bb","cc"];
var layers = d3.layout.stack()(headers.map(function(period) {
return data.map(function(d) {
return {x: d.Category, y: +d[period]};
});
}));
console.log(layers);
var yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); });
var yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
var yScale = d3.scale.ordinal()
.domain(layers[0].map(function(d) { return d.x; }))
.rangeRoundBands([25, height], .2);
var x = d3.scale.linear()
.domain([0, yStackMax])
.range([0, width]);
var color = d3.scale.ordinal()
.domain(headers)
.range(["#98ABC5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(1)
.tickPadding(15)
.tickFormat(d3.format(".2s"));
var yAxis = d3.svg.axis()
.scale(yScale)
.tickSize(0)
.tickPadding(6)
.orient("left");
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("y", function(d) { return yScale(d.x); })
.attr("x", 0)
.attr("height", yScale.rangeBand())
.attr("width", 0)
.on("click", function(d) {
console.log(d);
});
rect.transition()
.delay(function(d, i) { return i * 100; })
.attr("x", function(d) { return x(d.y0); })
.attr("width", function(d) { return x(d.y); });
//********** AXES ************
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text").style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(0,0)")
.call(yAxis)
.append("text")
.attr({"x": 0 / 2, "y": height+50})
.attr("dx", ".75em")
.style("text-anchor", "end")
.text("Time");
var legend = svg.selectAll(".legend")
.data(headers.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(-20," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
Problem:
I've got a D3.js scatter plot that has 16 different data sets, but it seems like D3 has only 10 different colours built-in before it repeats. You can see what I mean by clicking that link.
Code:
function updatePlot() {
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
});
x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice();
y.domain(d3.extent(data, function(d) { return d.sepalLength; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("HPF/LPF Intensity Ratio");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("HPF Intensity (relative units)")
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.style("fill", function(d) { return color(d.species); });
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
}
(The code is pretty much copy/paste from here with a little customisation in the areas of D3 that I understand)
Thanks!
This part of the docs has the answer: Ordinal-Scales#categorical-colors. Thanks to user and Lars Kotthoff!
Simply replaced category10 with category20.
I'm trying to figure out how to include 2 or more graphs on my website. I am currently using the Area Graph and the Pie Graph. If I disable one of them, then the other works fine, but when I try to use both at the same time, it stops working.
JS code for the Area Graph
var margin = { top: 0, right: 0, bottom: 30, left: 50 },
width = 670 - margin.left - margin.right,
height = 326 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#watLenYearGra").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var area = d3.svg.area()
.x(function (d) { return x(d.date); })
.y0(height)
.y1(function (d) { return y(d.close); });
$("#watLenYear").click(function () {
$("#watLenYearGra").slideToggle("fast");
});
d3.csv("data.csv", function (error, data) {
data.forEach(function (d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
x.domain(d3.extent(data, function (d) { return d.date; }));
y.domain([0, d3.max(data, function (d) { return d.close; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
svg.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
});
JS code for the Pie Graph
var width = 670,
height = 326,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function (d) { return d.population; });
var svg = d3.select("#watLenSzGra").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
$("#watLenSz").click(function () {
$("#watLenSzGra").slideToggle("fast");
});
d3.csv("data1.csv", function (error, data) {
data.forEach(function (d) {
d.population = +d.population;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function (d) { return color(d.data.age); });
g.append("text")
.attr("transform", function (d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function (d) { return d.data.age; });
});
I think the problem lies with the scope of the variables (specifically the svg variable since they have the same name). Right now I have these sets of code in separate JS files, and I link them at the bottom of my body tag in the HTML file.
How can I limit these variables' scope to their files? Is that even the problem? Thanks
It should work if you use closures:
(function() {
var margin = { top: 0, right: 0, bottom: 30, left: 50 },
width = 670 - margin.left - margin.right,
height = 326 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#watLenYearGra").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var area = d3.svg.area()
.x(function (d) { return x(d.date); })
.y0(height)
.y1(function (d) { return y(d.close); });
$("#watLenYear").click(function () {
$("#watLenYearGra").slideToggle("fast");
});
d3.csv("data.csv", function (error, data) {
data.forEach(function (d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
x.domain(d3.extent(data, function (d) { return d.date; }));
y.domain([0, d3.max(data, function (d) { return d.close; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
svg.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
});
})();
(function() {
var width = 670,
height = 326,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function (d) { return d.population; });
var svg = d3.select("#watLenSzGra").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
$("#watLenSz").click(function () {
$("#watLenSzGra").slideToggle("fast");
});
d3.csv("data1.csv", function (error, data) {
data.forEach(function (d) {
d.population = +d.population;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function (d) { return color(d.data.age); });
g.append("text")
.attr("transform", function (d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function (d) { return d.data.age; });
});
})();