|
// Width, height, margins for axes |
|
var margin = {top: 10, right: 50, bottom: 10, left: 40}; |
|
w = 700 - margin.right - margin.left, |
|
h = 500 - margin.top - margin.bottom; |
|
|
|
// Data global vars |
|
var alzheimerData, |
|
vizData, |
|
vizKeys, |
|
vizColumns = [], |
|
vizFilters = [function(d) { return (d["GBD Region"] == "World"); }, |
|
function(d) { return (d["Region Type"] == "Global" && d["GBD Region"] != "World"); }]; |
|
|
|
// Colours |
|
var colours = ["#FF6666", "#CCFF66", "#5D2E8C", "#2EC4B6", "#FFA9E7", "#F7A072", "#0FA3B1", "#B388EB", "#FFB4A2", "#6BFFB8", "#B7AD99", "#9395D3", "#B66D0D", "#2176AE", "#69626D", "#FF5964"]; |
|
|
|
// Set up SVG container |
|
var svgContainer = d3.select("#chart").append("svg") |
|
.attr("class", "container") |
|
.attr("width", w + margin.right + margin.left) |
|
.attr("height", h + margin.top + margin.bottom) |
|
.append("g") |
|
.attr("transform", |
|
"translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
// Get the data |
|
d3.csv("alzheimer.csv", |
|
function(d) { |
|
d3.keys(d).forEach(function(k) { |
|
if (k.indexOf("Region") == -1) { d[k] = +d[k]; }; |
|
if (k.indexOf("millions") != -1) { d[k] = d[k] * 1000000; } |
|
}); |
|
return d; |
|
}, |
|
function(error, data) { |
|
// Check for error |
|
if (error) { console.log(error); } |
|
|
|
alzheimerData = data; |
|
generateViz(vizFilters); |
|
} |
|
); |
|
|
|
//Create the Scale we will use for the Axis |
|
var xScale = d3.scale.ordinal() |
|
.rangeRoundBands([0,w - margin.right - margin.left], 0.1); |
|
|
|
var yScale = d3.scale.linear() |
|
.range([h - margin.top - margin.bottom,0]).nice(); |
|
|
|
var cScale = d3.scale.ordinal(); |
|
|
|
var generateViz = function(filters) { |
|
// Apply data filter |
|
vizData = alzheimerData.filter(filters[0]); |
|
filters = filters.slice(1); |
|
|
|
// Select columns we'll need + initialise totals |
|
vizKeys = d3.keys(vizData[0]) |
|
.filter(function(d) { return d.indexOf("Number of people with dementia") == 0; }) |
|
.map(function(d) { return { name: d, total: +0, year: d.slice(42,46) } }); |
|
|
|
var key = 1; |
|
// Create column data |
|
vizData.forEach(function(d) { |
|
d3.keys(vizKeys).forEach(function(i) { |
|
if (d3.keys(vizColumns).indexOf(vizKeys[i].name) > -1) { |
|
vizColumns[vizKeys[i].name].push({ |
|
key: key, |
|
region: d["GBD Region"], |
|
year: vizKeys[i].year, |
|
y0: vizKeys[i].total, |
|
y1: vizKeys[i].total += d[vizKeys[i].name] |
|
}); |
|
} else { |
|
vizColumns[vizKeys[i].name] = [{ |
|
key: key, |
|
region: d["GBD Region"], |
|
year: vizKeys[i].year, |
|
y0: vizKeys[i].total, |
|
y1: vizKeys[i].total += d[vizKeys[i].name] |
|
}]; |
|
|
|
}; |
|
key += 1; |
|
}); |
|
}); |
|
var tmpVizColumns = []; |
|
for (i=0; i < vizKeys.length; i++) { |
|
tmpVizColumns = tmpVizColumns.concat(vizColumns[vizKeys[i].name]); |
|
}; |
|
vizColumns = tmpVizColumns; |
|
|
|
// Reset scales |
|
regions = vizColumns.map(function(d) { return d.region }) |
|
.filter(function(value, index, self) { |
|
return self.indexOf(value) === index; |
|
}); |
|
cScale = cScale.domain(regions) |
|
.range(colours.slice(0,regions.length)); |
|
yScale = yScale.domain([0,d3.max(vizKeys.map(function(d) { return d.total; }))]); |
|
xScale = xScale.domain(vizKeys.map(function(d) { return d.year; }).sort()); |
|
|
|
// Create chart |
|
var chartElements = svgContainer.selectAll("rect.barchart") |
|
.data(vizColumns, function(d) { |
|
return d.key; |
|
}) |
|
.enter() |
|
.append("rect") |
|
.attr("class", "barchart") |
|
.attr("x", function(d) { return xScale(d.year); } ) |
|
.attr("y", yScale(0)) |
|
.attr("fill", function(d) { return cScale(d.region); } ) |
|
.attr("width", xScale.rangeBand()) |
|
.attr("height", 0); |
|
|
|
chartElements |
|
.transition() |
|
.duration(500) |
|
.attr("y", function(d) { return yScale(d.y1); } ) |
|
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); } ); |
|
|
|
// Axes |
|
var xAxis = d3.svg.axis() |
|
.scale(xScale) |
|
.orient("bottom"); |
|
|
|
svgContainer.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + (h - margin.bottom - margin.top) + ")") |
|
.call(xAxis); |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(yScale) |
|
.orient("left") |
|
.tickFormat(d3.format("s")); |
|
|
|
svgContainer.append("g") |
|
.attr("class", "y axis") |
|
.call(yAxis) |
|
.append("text") |
|
.attr("transform", "rotate(-90)") |
|
.attr("y", 10) |
|
.attr("dy", ".71em") |
|
.style("text-anchor", "end") |
|
.text("Population with Dementia"); |
|
|
|
// Legend |
|
var legend = svgContainer.selectAll(".legend") |
|
.data(cScale.domain().slice().reverse()) |
|
.enter().append("g") |
|
.attr("class", "legend") |
|
.attr("transform", function(d, i) { return "translate(" + w + "," + (i * 20) + ")"; }); |
|
|
|
legend.append("rect") |
|
.attr("width", 18) |
|
.attr("height", 18) |
|
.style("fill", cScale); |
|
|
|
legend.append("text") |
|
.attr("y", 9) |
|
.attr("x", -5) |
|
.attr("dy", ".35em") |
|
.style("text-anchor", "end") |
|
.text(function(d) { return d; }); |
|
|
|
// Add expand button |
|
if(filters.length > 0) { |
|
svgContainer.append("g") |
|
.attr("class", "legend expand") |
|
.attr("transform", "translate(" + w + "," + ((cScale.domain().slice().reverse().length + 1) * 20) + ")") |
|
.append("text") |
|
.attr("y", 9) |
|
.attr("x", -5) |
|
.attr("dy", ".35em") |
|
.style("text-anchor", "end") |
|
.text("DRILL IN!"); |
|
|
|
svgContainer.select(".expand") |
|
.on("click", function() { updateViz(filters); }); |
|
} |
|
}; |
|
|
|
var updateViz = function(filters) { |
|
// Apply data filter |
|
vizData = alzheimerData.filter(filters[0]); |
|
filters = filters.slice(1); |
|
|
|
// Select columns we'll need + initialise totals |
|
vizKeys = d3.keys(vizData[0]) |
|
.filter(function(d) { return d.indexOf("Number of people with dementia") == 0; }) |
|
.map(function(d) { return { name: d, total: +0, year: d.slice(42,46) } }); |
|
var key = 1; |
|
// Create column data |
|
vizData.forEach(function(d) { |
|
d3.keys(vizKeys).forEach(function(i) { |
|
if (d3.keys(vizColumns).indexOf(vizKeys[i].name) > -1) { |
|
vizColumns[vizKeys[i].name].push({ |
|
key: key, |
|
region: d["Sub-Region"], |
|
year: vizKeys[i].year, |
|
y0: vizKeys[i].total, |
|
y1: vizKeys[i].total += d[vizKeys[i].name] |
|
}); |
|
} else { |
|
vizColumns[vizKeys[i].name] = [{ |
|
key: key, |
|
region: d["Sub-Region"], |
|
year: vizKeys[i].year, |
|
y0: vizKeys[i].total, |
|
y1: vizKeys[i].total += d[vizKeys[i].name] |
|
}]; |
|
|
|
}; |
|
key += 1; |
|
}); |
|
}); |
|
var tmpVizColumns = []; |
|
for (i=0; i < vizKeys.length; i++) { |
|
tmpVizColumns = tmpVizColumns.concat(vizColumns[vizKeys[i].name]); |
|
}; |
|
vizColumns = tmpVizColumns; |
|
|
|
// Reset scales |
|
regions = vizColumns.map(function(d) { return d.region }) |
|
.filter(function(value, index, self) { |
|
return self.indexOf(value) === index; |
|
}); |
|
cScale = cScale.domain(regions) |
|
.range(colours.slice(0,regions.length)); |
|
|
|
// Remove data |
|
//svgContainer.selectAll("rect.barchart").remove(); |
|
|
|
// Create chart |
|
var chartElements = svgContainer.selectAll("rect.barchart") |
|
.data(vizColumns, function(d) { |
|
return d.key; |
|
}); |
|
|
|
|
|
chartElements.transition() |
|
.duration(500) |
|
.attr("class", "barchart") |
|
.attr("x", function(d) { return xScale(d.year); } ) |
|
.attr("y", function(d) { return yScale(d.y1); } ) |
|
.attr("fill", function(d) { return cScale(d.region); } ) |
|
.attr("width", xScale.rangeBand()) |
|
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); } ); |
|
|
|
|
|
var newChartElements = chartElements.enter() |
|
.append("rect") |
|
.attr("class", "barchart") |
|
.attr("x", function(d) { return xScale(d.year); } ) |
|
.attr("y", function(d) { return yScale(d.y0); } ) |
|
.attr("fill", function(d) { return cScale(d.region); } ) |
|
.attr("width", xScale.rangeBand()) |
|
.attr("height", 0); |
|
|
|
newChartElements.transition() |
|
.delay(500) |
|
.duration(500) |
|
.attr("y", function(d) { return yScale(d.y1); } ) |
|
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); } ); |
|
|
|
// Legend |
|
svgContainer.selectAll(".legend").remove(); |
|
|
|
var legend = svgContainer.selectAll(".legend") |
|
.data(cScale.domain().slice().reverse()) |
|
.enter().append("g") |
|
.attr("class", "legend") |
|
.attr("transform", function(d, i) { return "translate(" + w + "," + (i * 20) + ")"; }); |
|
|
|
legend.append("rect") |
|
.attr("width", 18) |
|
.attr("height", 18) |
|
.style("fill", cScale); |
|
|
|
legend.append("text") |
|
.attr("y", 9) |
|
.attr("x", -5) |
|
.attr("dy", ".35em") |
|
.style("text-anchor", "end") |
|
.text(function(d) { return d; }); |
|
|
|
// Add expand button |
|
if(filters.length > 0) { |
|
svgContainer.append("g") |
|
.attr("class", "legend expand") |
|
.attr("transform", "translate(" + w + "," + ((cScale.domain().slice().reverse().length + 1) * 20) + ")") |
|
.append("text") |
|
.attr("y", 9) |
|
.attr("x", -5) |
|
.attr("dy", ".35em") |
|
.style("text-anchor", "end") |
|
.text("DRILL IN!"); |
|
|
|
svgContainer.select(".expand") |
|
.on("click", function() { updateViz(filters); }); |
|
} |
|
}; |