Reputation: 581
I have a real simple horizontally stacked bar chart with 3 bars that are all on the same scale (i.e. each 0 to 100 with the stacked bars consisting of numbers that make up 100).
When trying to update my data nothing appears to happen. I've not been able to figure out how to update the data and it's been driving me crazy.
Relevant Code:
<body>
<div id='updateTest'>
Update Data
</div>
<div id='chart'></div>
<script>
$( document ).ready(function() {
$( "#updateTest" ).click(function() {
updateData();
console.log(allData[count]);
});
});
var institution;
// Set up the SVG data
var allData = ["data.csv","data2.csv","data3.csv"];
var count = 0;
var margin = {top: 20, right: 20, bottom: 145, left: 115},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0], .1);
var x = d3.scale.linear()
.rangeRound([0, width]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888"]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart").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 + ")");
// Bind initial shown data to the SVG
d3.csv(allData[count], function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "Institution";
}));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {name: name, y0: y0, y1: y0 += +d[name]};
});
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
y.domain(data.map(function(d) { return d.Institution; }));
x.domain([0, d3.max(data, function(d) { return d.total; })]);
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("x", -32)
.attr("y", -112)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Institution");
institution = svg.selectAll(".institution")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) {
return "translate(0," + y(d.Institution) + ")"; });
institution.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.y0); })
.attr("width", function(d) { return x(d.y1) - x(d.y0); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 28 + ")"; });
legend.append("rect")
.attr("x", -20)
.attr("y", 190)
.attr("width", 25)
.attr("height", 25)
.style("fill", color);
legend.append("text")
.attr("x", 10)
.attr("y", 203)
.attr("dy", ".35em")
.style("text-anchor", "left")
.text(function(d) { return d; });
});
/* updateData()
* Rebinds the SVG to a new dataset
*/
function updateData() {
// Iterate through the data
var newData;
if (count === allData.length - 1)
count = 0;
else
count++;
newData = allData[count];
// Get the data again
d3.csv(allData[count], function(error, data) {
data.forEach(function(d) {
d.close = +d.close;
});
// Make the changes
institution.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.y0); })
.attr("width", function(d) { return x(d.y1) - x(d.y0); })
.style("fill", function(d) { return color(d.name); });
});
}
</script>
</body>
My CSV files:
data.csv
Institution,CurrentlyOweBehind,CurrentlyOweNotBehind,Paid
For-profit,15,35,50
Nonprofit,11,48,41
Public,26,16,58
data2.csv
Institution,CurrentlyOweBehind,CurrentlyOweNotBehind,Paid
For-profit,23,33,44
Nonprofit,28,12,60
Public,12,8,80
data3.csv
Institution,CurrentlyOweBehind,CurrentlyOweNotBehind,Paid
For-profit,61,22,17
Nonprofit,7,43,50
Public,41,19,40
The main bit is in the updateData()
function. I am able to create the chart and display data but I do not understand transitioning the data...
I'm getting no errors in the console and it's properly cycling the data.
Upvotes: 0
Views: 187
Reputation: 786
The problems is with d.ages in the update function. You basically need the same setup that you have for the initial plot. So I added the following in the d3.csv block of your update function:
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {name: name, y0: y0, y1: y0 += +d[name]};
});
d.total = d.ages[d.ages.length - 1].y1;
});
institution = svg.selectAll(".institution")
.data(data);
The class name for institution
was set to g for some reason, and I changed that to institution. Also, you do not need .enter().append("rect")
at this point. Finally I added a transition and duration.
I have created a plunk, with all your csv files included: http://plnkr.co/edit/CYFNWZKuiLo9gFps49e9?p=preview
Hope this helps.
Upvotes: 1