D3 enter-exit-update and pie charts - javascript

So, I've been updating a functioning but not elegant D3 chart using https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter9/pie-chart.html
My class looks like this:
function doughnutChart(selector_div) {
"use strict";
var _chart = {};
var _width = 200, _height = 200,
_data = [],
_svg, _bodyG, _pieG,
_radius = 100,
_inner_radius = 50;
_chart.render = function() {
if (!_svg) {
_svg = d3.select(selector_div).append("svg")
.attr("height", _height)
.attr("width", _width);
}
renderBody(_svg);
};
function renderBody(svg) {
if (!_bodyG) {
_bodyG = svg.append("g")
.attr("class", "body");
}
renderDoughnut();
}
function renderDoughnut() {
var pie = d3.layout.pie()
.sort(function (d) {
return d.id;
})
.value(function (d) {
return d.count + d.abnormal;
});
var arc = d3.svg.arc()
.outerRadius(_radius)
.innerRadius(_inner_radius);
if (!_pieG) {
_pieG = _bodyG.append("g")
.attr("class", "pie")
.attr("transform", "translate("
+ _radius
+ ","
+ _radius + ")");
}
renderSlices(pie, arc);
renderLabels(pie, arc);
}
}
function renderSlices(pie, arc) {
var slices = _pieG.selectAll("path.arc")
.data(pie(_data));
slices.enter()
.append("path")
.attr("class", "arc")
.attr("fill", function(d) {
return d.data.visualisation_colour;
});
slices.transition()
.attrTween("d", function(d) {
var currentArc = this.__current__;
if (!currentArc) {
currentArc = {startAngle: 0, endAngle: 0};
}
var interpolate = d3.interpolate(currentArc, d);
this.__current__ = interpolate(1);
return function(t) {
return arc(interpolate(t));
};
});
}
function renderLabels() {
_pieG.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "inside")
.text(function(d) {
var total = 0;
for (var j = 0; j < _data.length; j++) {
total = total + _data[j].count + _data[j].abnormal;
}
return total;
});
}
_chart.data = function(d) {
if (!arguments.length) {
return _data;
}
_data = d;
return _chart;
};
return _chart;
}
When I use:
var chart = doughnutChart("#chart").data(data);
chart.render()
I get a nice chart rendered. But the update doesn't work:
data = $.map(cell_types, function(key, value) {
return key;
});
chart.render();
The main issue is:
How do I update this chart? I'm not sure how to get updated data into the chart. Calling render() again does not update the data despite the data variable being updated, and I can't seem to pass new data in. The book's example doesn't appear to have this issue, as testing that works without issue.

There is actually a simple error in syntax here:
if (!_pieG) {
_pieG = _bodyG.append("g")
.attr("class", "pie")
.attr("transform", "translate("
+ _radius
+ ","
+ _radius + ")");
renderSlices(pie, arc);
renderLabels(pie, arc);
}
Should actually be:
if (!_pieG) {
_pieG = _bodyG.append("g")
.attr("class", "pie")
.attr("transform", "translate("
+ _radius
+ ","
+ _radius + ")");
}
renderSlices(pie, arc);
renderLabels(pie, arc);
And then it updates correctly.

Related

Stacked area graph not rendering

I have a stacked area chart that reads from CSV. But it doesn't render the x axis and the graph correctly.
I have tried to change the x axis values, but didn't help.
below is the sample CSV file.
Currently the view shows the y axis of values, and the drug names on the right, but it doesn't show the actual stacked chart or the date x axis values.
So far return x(d.data.date) = returning NaN.
Thank you so much for your help!
date,drug,market_share
2016-01-01,insulin lispro,.01
2016-01-01,alogliptin,0.001323754341
2016-01-01,sitagliptin,.01
2016-01-01,canagliflozin,0.02842158621
2016-01-01,glimepiride,0.05668845799
2016-01-01,repaglinide,0.0005768749342
2016-01-01,insulin glargine,.01
2016-01-01,metformin,0.4972895171
2016-01-01,mifepristone,.02
2016-01-01,exenatide,.02
2016-01-01,bromocriptine,0.0002109506723
2016-01-01,pioglitazone,0.02324500184
2016-01-01,metformin hydrochloride,0.392074889
2016-02-01,saxagliptin,.02
2016-02-01,pioglitazone,0.02247815103
2016-02-01,exenatide,0.03
2016-02-01,repaglinide,0.0006204220565
2016-02-01,metformin hydrochloride,0.394153624
2016-02-01,sitagliptin,.08
2016-02-01,insulin lispro,.05
2016-02-01,canagliflozin,0.02907988245
2016-02-01,metformin,0.4933502396
2016-02-01,insulin glargine,.02
2016-02-01,bromocriptine,0.0002076549233
2016-02-01,mifepristone,.02
2016-02-01,alogliptin,0.001364306972
2016-02-01,glimepiride,0.05857620484
2016-03-01,canagliflozin,0.02908102306
2016-03-01,bromocriptine,0.000195238081
2016-03-01,metformin,0.4966376769
2016-03-01,alogliptin,0.00133532899
2016-03-01,insulin glargine,.03
2016-03-01,sitagliptin,.04
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="div1"></div>
<div id="div2"></div>
</body>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
var parseDate = d3.timeParse("%Y-%m-%d");
function type2(d, i, columns) {
d.date = parseDate(d.date);
return d;
}
function type(d, i, columns) {
d.date = parseDate(d.date);
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = d[columns[i]] / 100;
return d;
}
function drawGraph(error, data, selector, width, height) {
console.log("DATA "+selector+JSON.stringify(data));
console.log("COL "+selector+"---"+data.columns);
var svg = d3.select(selector).append("svg")
.attr("width", width)
.attr("height", height),
margin = {top: 20, right: 20, bottom: 30, left: 50},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var stack = d3.stack();
var area = d3.area()
.x(function (d, i) {
return x(d.data.date);
})
.y0(function (d) {
return y(d[0]);
})
.y1(function (d) {
return y(d[1]);
});
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var keys = data.columns.slice(1);
x.domain(d3.extent(data, function (d) {
return d.date;
}));
z.domain(keys);
stack.keys(keys);
console.log("Stacked Data "+ selector+"---" + JSON.stringify(stack(data)));
var layer = g.selectAll(".layer")
.data(stack(data))
.enter().append("g")
.attr("class", "layer");
layer.append("path")
.attr("class", "area")
.style("fill", function (d) {
return z(d.key);
})
.attr("d", area);
layer.filter(function (d) {
return d[d.length - 1][1] - d[d.length - 1][0] > 0.01;
})
.append("text")
.attr("x", width - 6)
.attr("y", function (d) {
return y((d[d.length - 1][0] + d[d.length - 1][1]) / 2);
})
.attr("dy", ".35em")
.style("font", "10px sans-serif")
.style("text-anchor", "end")
.text(function (d) {
return d.key;
});
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "%"));
}
d3.csv("market_shares.csv", type2, function (error, data) {
let stackedByDate = {}
let drugSet = new Set();
let defaultDrugMarketShareProp = {};
let newData = []
data.forEach(function (item, index) {
drugSet.add(item.drug);
stackedByDate[item.date] = {};
});
let drugNames = [...drugSet];
drugNames.forEach(function (item, index) {
defaultDrugMarketShareProp[item] = 0;
});
data.forEach(function (item, index) {
stackedByDate[item.date] = Object.assign({}, defaultDrugMarketShareProp);
});
data.forEach(function (item, index) {
stackedByDate[item.date][item.drug] = item.market_share;
});
Object.keys(stackedByDate).forEach(function (key) {
hash = {}
hash['date'] = key;
Object.keys(stackedByDate[key]).forEach(function (innerKey) {
hash[innerKey] = stackedByDate[key][innerKey]
});
newData.push(hash);
});
newData.columns = drugNames;
newData.columns.unshift('date');
drawGraph(error, newData, "#div2", 960, 500);
});
</script>
You correctly parsed the date strings. However, in this function...
Object.keys(stackedByDate).forEach(function (key) {
hash = {}
hash['date'] = key;//<----- HERE
Object.keys(stackedByDate[key]).forEach(function (innerKey) {
hash[innerKey] = stackedByDate[key][innerKey]
});
newData.push(hash);
});
... you're converting the date objects back to strings again.
The quickest solution is just:
hash['date'] = new Date(key);
Here is your code with that change only: https://bl.ocks.org/GerardoFurtado/e9538de82e96cc9e3efb5fc4c7b9b970/5ca6920405243c39b93d0245230b955c37c85a2c

Label names are not displayed from input data in pie transition chart of d3.js

I am using d3.js to draw a pie transition chart. But when labels are placed in the data array as show below:
data = [{"label":"sector1", "value":25}, {"label":"sector2", "value":45}]
The pie chart won't be displayed. Instead "NaN" will be printed.
The complete code is pasted below:
var w = 400,
h = 400,
r = Math.min(w, h) / 2,
data = [{"label":"sector1", "value":25}, {"label":"sector2", "value":45}], // Data with label-value pairs
color = d3.scale.category20(),
arc = d3.svg.arc().outerRadius(r),
donut = d3.layout.pie();
var vis = d3.select("body").append("svg") // Place the chart in 'pie-chart-div'
.data([data])
.attr("width", w)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut)
.enter().append("g")
.attr("class", "arc")
.attr("transform", "translate(" + r + "," + r + ")");
var paths = arcs.append("path")
.attr("fill", function(d, i) { return color(i); });
var labels = arcs.append("text")
.attr("transform", function(d) { d.innerRadius = 120; return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.text(function(d) { return d.value; });
paths.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
paths.transition()
.ease("elastic")
.delay(function(d, i) { return 2000 + i * 50; })
.duration(750)
.attrTween("d", tweenDonut);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) {
return arc(i(t));
};
}
function tweenDonut(b) {
b.innerRadius = r * .6;
var i = d3.interpolate({innerRadius: 0}, b);
return function(t) {
return arc(i(t));
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
How to display the label names along with the values in the chart ?
You need to call donut with your data inside like that :
data2 = data.map(function(d) { return d.value}) // [25, 45]
...
.data(donut(data2))
and then call the label ;
.text(function(d, i) { return data[i].label; });
See http://jsfiddle.net/980f0cdj/1/

Why does calling d3.scale.linear.domain after data update squishes the scale?

I'm using d3js for an interactive chart where you can enter data and the chart values will get updated. The chart is a basic 2d line chart that has {date, value} pairs. This is the code I'm using every time there's a new data update, to refresh the chart:
function fetchLatest()
{
// get data from server
$.getJSON('/dataset',
function(data)
{
var data_etl = [];
data_etl = data.map(function(d){
return { x: parseDate(d.date), y: d.value };
});
var xScale = d3.scale.ordinal().rangeRoundPoints([0, options.width - 97]);
var yScale = d3.scale.linear();
chart
.width($('.livechart').width())
.height(300)
.x(xScale.domain(data_etl.map(function(d){ return d.x; })));
.y(yScale.domain([0, d3.max(data_etl, function(d) { return d.y;} )+1])); // PROBLEM LINE
chart.replaceSeries(data_etl);
chart.render();
});
}
The issue is that while the chart appear perfectly the first time it is loaded, upon reloading (new data update), the y-scale gets completely squished (so the line becomes a flat horizontal line). I did some debugging, and pinpointed the issue to this line:
.y(yScale.domain([0, d3.max(data_etl, function(d) { return d.y;} )+1]));
If on update I don't call this line, then the chart is updated fine. However, if I call it, it causes the issue mentioned above. Does anyone know why this is happening?
Edit Per note from meetamit, there isn't enough information. I'm adding the chart object code as well:
function lineChart(insertionPoint) {
var _chart = {};
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
var tip_date = "<span style='color:#f78b20'>" + formatDate(d.x) + ": </span>";
var tip_activity = d.y;
return tip_date + tip_activity;
});
var _width = 600, _height = 300,
_margins = {top: 40, left: 40, right: 40, bottom: 40},
_x, _y,
_data = [],
_colors = d3.scale.ordinal().range([
'#33ccff', '#f78b20', '#99dc2a', '#57d4d3'
]),
_svg,
_bodyG,
_line;
_chart.render = function () {
if (!_svg) {
_svg = d3.select(insertionPoint).append("svg") // <-2B
.attr("height", _height)
.attr("width", _width);
renderAxes(_svg);
defineBodyClip(_svg);
}
renderBody(_svg);
_svg.call(tip);
};
function renderAxes(svg) {
var axesG = svg.append("g")
.attr("class", "axes");
renderXAxis(axesG);
renderYAxis(axesG);
}
function renderXAxis(axesG){
// xAxis
var xAxis = d3.svg.axis()
//.scale(_x.range([0, quadrantWidth()]))
.scale(_x)
.orient("bottom")
.tickFormat(d3.time.format("%m-%d"));
axesG.append("g")
.attr("class", "x axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yStart() + ")";
})
.call(xAxis);
}
function renderYAxis(axesG){
//yAxis
var yAxis = d3.svg.axis()
.scale(_y.range([quadrantHeight(), 0]))
.orient("left");
axesG.append("g")
.attr("class", "y axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yEnd() + ")";
})
.call(yAxis);
}
function defineBodyClip(svg) {
var padding = 5;
svg.append("defs")
.append("clipPath")
.attr("id", "body-clip")
.append("rect")
.attr("x", 0 - padding)
.attr("y", 0)
.attr("width", quadrantWidth() + 2 * padding)
.attr("height", quadrantHeight());
}
function renderBody(svg) {
if (!_bodyG)
_bodyG = svg.append("g")
.attr("class", "body")
.attr("transform", "translate("
+ xStart() + ","
+ yEnd() + ")") // <-2E
.attr("clip-path", "url(#body-clip)");
renderLines();
renderDots();
}
function renderLines() {
_line = d3.svg.line()
.x(function (d) { return _x(d.x); })
.y(function (d) { return _y(d.y); });
_bodyG.selectAll("path.line")
.data(_data)
.enter()
.append("path")
.style("stroke", function (d, i) {
return _colors(i);
})
.attr("class", "line");
_bodyG.selectAll("path.line")
.data(_data)
.transition()
.attr("d", function (d) { return _line(d); });
}
function renderDots() {
_data.forEach(function (list, i) {
_bodyG.selectAll("circle._" + i)
.data(list)
.enter()
.append("circle")
.attr("class", "dot _" + i)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on('click', function(d, i){
showTotalActivities(d.x);
});
_bodyG.selectAll("circle._" + i)
.data(list)
.style("stroke", function (d) {
return _colors(i); //<-4F
})
.transition() //<-4G
.attr("cx", function (d) {
return _x(d.x); })
.attr("cy", function (d) {
//console.log("dy: " + _y(d.y));
return _y(d.y); })
.attr("r", 4.5);
});
}
function xStart() {
return _margins.left;
}
function yStart() {
return _height - _margins.bottom;
}
function xEnd() {
return _width - _margins.right;
}
function yEnd() {
return _margins.top;
}
function quadrantWidth() {
return _width - _margins.left - _margins.right;
}
function quadrantHeight() {
return _height - _margins.top - _margins.bottom;
}
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
return _chart;
};
_chart.height = function (h) {
if (!arguments.length) return _height;
_height = h;
return _chart;
};
_chart.margins = function (m) {
if (!arguments.length) return _margins;
_margins = m;
return _chart;
};
_chart.colors = function (c) {
if (!arguments.length) return _colors;
_colors = c;
return _chart;
};
_chart.x = function (x) {
if (!arguments.length) return _x;
_x = x;
return _chart;
};
_chart.y = function (y) {
if (!arguments.length) return _y;
_y = y;
return _chart;
};
_chart.addSeries = function (series) {
_data.push(series);
return _chart;
};
_chart.replaceSeries = function (series) {
_data = [];
_data.push(series);
return _chart;
};
return _chart;
}

arctween and dataset change in donut chart with d3,js

With the click of a button, I want to add a new dataset to my doughnut chart and have it transition the new dataset. The code I've written sort of does that but it runs into an issue when the number of individual data within the dataset is different from the previous i.e. going from [1,2] to [1,2,3,4].
I think the issue is that I need to create a new path whenever there the new dataset has more data, and remove paths whenever it has less. However, when I try to append data in my click function, it will append it without removing the old paths and will overlap on the chart.
Here is a version without appending, where the arctween will work but there will be empty pie arcs because I don't append path (arctween works half the time):
http://jsfiddle.net/njrPF/1/
var pieW = 500;
var pieH = 500;
var innerRadius = 100;
var outerRadius = 200;
var results_pie = d3.layout.pie()
.sort(null);
var pie_arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var svg_pie = d3.select("#pieTotal")
.attr("width", pieW)
.attr("height", pieH)
.append("g")
.attr("transform", "translate(" + pieW / 2 + "," + pieH / 2 + ")")
.attr("class", "piechart");
var pie_path = svg_pie.selectAll("path").data(results_pie([1, 2]))
.enter().append("path")
.attr("d", pie_arc)
.each(function (d) {
this._current = d;
}) // store the initial values
.attr("class", "vote_arc")
.attr("value", function (d, i) {
return (i - 1);
});
var pie_votes = [1, 2];
var pie_colors = ["#0f0", "#f00"];
$(svg_pie).bind("monitor", worker);
$(svg_pie).trigger("monitor");
function worker(event) {
pie_path = pie_path.data(results_pie(pie_votes))
.attr("fill", function (d, i) {
return pie_colors[i];
});
pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) {
if (d.value <= 0) {
this.remove();
}
});
setTimeout(function () {
$(svg_pie).trigger("monitor");
}, 500);
}
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return pie_arc(i(t));
};
}
$('button').click(function () {
pie_votes = [];
pie_colors = [];
for (var i = 0; i < Math.floor(Math.random() * 6); i++) {
//sets new values on pie arcs
pie_votes.push(Math.floor(Math.random() * 10));
pie_colors.push("#" + (Math.floor(Math.random() * 16777215)).toString(16));
}
pie_path = pie_path.data(results_pie(pie_votes))
.attr("fill", function (d, i) {
return pie_colors[i]
});
pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) {
if (d.value <= 0) {
this.remove();
}
});
});
Here is a version where I try to append new paths but they overlap:
http://jsfiddle.net/njrPF/3/
var pieW = 500;
var pieH = 500;
var innerRadius = 100;
var outerRadius = 200;
var results_pie = d3.layout.pie()
.sort(null);
var pie_arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var svg_pie = d3.select("#pieTotal")
.attr("width", pieW)
.attr("height", pieH)
.append("g")
.attr("transform", "translate(" + pieW / 2 + "," + pieH / 2 + ")")
.attr("class", "piechart");
var pie_path = svg_pie.selectAll("path").data(results_pie([1, 2]))
.enter().append("path")
.attr("d", pie_arc)
.each(function (d) {
this._current = d;
}) // store the initial values
.attr("class", "vote_arc")
.attr("value", function (d, i) {
return (i - 1);
});
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return pie_arc(i(t));
};
}
$('button').click(function () {
pie_votes = [];
pie_colors = [];
for (var i = 0; i < Math.floor(Math.random() * 10); i++) {
//sets new values on pie arcs
pie_votes.push(Math.floor(Math.random() * 10));
pie_colors.push("#" + (Math.floor(Math.random() * 16777215)).toString(16));
}
pie_path = pie_path.data(results_pie(pie_votes))
.enter().append("path")
.attr("d", pie_arc)
.each(function (d) {
this._current = d; }) // store the initial values
.attr("class", "vote_arc")
.attr("value", function (d, i) {
return (i - 1);
});
pie_path.attr("fill", function (d, i) {
return pie_colors[i]
});
pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) {
if (d.value <= 0) {
this.remove();
}
});
});
Thanks in advance.
You need to handle the enter and exit selections as well as the update selection. See for example this tutorial. The relevant code in your case would be
pie_path = pie_path.data(results_pie(pie_votes));
pie_path.enter().append("path")
.attr("d", pie_arc)
.each(function (d) {
this._current = d;
}) // store the initial values
.attr("class", "vote_arc")
.attr("value", function (d, i) {
return (i - 1);
});
pie_path.exit().remove();
Complete example here.

d3.js dynamic data with labels

I've managed to get the following working (pie chart changing dynamically based on a slider value):
var x = function() {
return $("#slider").val();
}
var data = function() {
return [x(), ((100-x())/2), ((100-x())/2)];
}
var w = 100,
h = 100,
r = 50,
color = d3.scale.category20(),
pie = d3.layout.pie().sort(null),
arc = d3.svg.arc().outerRadius(r);
var svg = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
var arcs = svg.selectAll("path")
.data(pie(data()))
.enter().append("svg:path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { this._current = d; });
var redraw = function() {
newdata = data(); // swap the data
arcs = arcs.data(pie(newdata)); // recompute the angles and rebind the data
arcs.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
};
// Store the currently-displayed angles in this._current.
// Then, interpolate from this._current to the new angles.
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
I can't seem to modify it to include dynamic labels (use an object for data rather than an array {'label': 'label1', 'value': value}. How would I modify the above code to add labels?
This should work, keeping the labels and the pie chart as separate entities:
var x = function() {
return $("#slider").val();
}
var data = function() {
return [x(), ((100-x())/2), ((100-x())/2)];
}
var labels = function() {
var label1 = "LABEL 1: " + x();
var label2 = "LABEL 2: " + ((100-x())/2);
var label3 = "LABEL 3: " + ((100-x())/2);
return [label1, label2, label3];
}
var w = 200,
h = 100,
r = 50,
color = d3.scale.category20(),
pie = d3.layout.pie().sort(null),
arc = d3.svg.arc().outerRadius(r);
var svg = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + 50 + "," + h / 2 + ")");
var arcs = svg.selectAll("path")
.data(pie(data()))
.enter().append("svg:path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { this._current = d; });
var label_group = svg.selectAll("text")
.data(labels())
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("x", 60)
.attr("y", function(d, i) { return (i * 20) - 16; });
var redraw = function() {
newdata = data(); // swap the data
arcs = arcs.data(pie(newdata)); // recompute the angles and rebind the data
arcs.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
label_group = label_group.data(labels());
label_group.transition().delay(300).text(function(d) {
return d;
});

Categories

Resources