xxxxxxxxxx
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-ease.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-selection.v1.min.js"></script>
<script src="https://d3js.org/d3-timer.v1.min.js"></script>
<script src="https://d3js.org/d3-transition.v1.min.js"></script>
<script>
var transition = d3.transition();
</script>
<style type="text/css">
button {
max-width: 600px;
text-align: center;
font-family: Futura;
font-size: 10px;
padding: 8px;
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
outline-style: hidden;
opacity: .8;
color: inherit;
}
.axis line {
stroke-opacity: .5;
stroke: #fff;
}
.axis text {
font-family: Futura;
font-size: 10px;
}
.x text {
text-anchor: end;
}
.background {
fill: #bfbfbf;
fill-opacity: .75;
}
.domain {
fill: none;
stroke: #F8F3D4;
}
.dots {
fill: #000FB8;
stroke: #fff;
}
.incomeLine {
fill: none;
stroke: white;
stroke-width: 3;
}
#countryButtons {
fill: white;
max-width: 800px;
text-align: center;
font-family: Futura;
padding: 2px;
}
</style>
<body>
<div id='countryButtons'></div>
</body>
<div id='chart-container'></div>
</body>
<script>
var margin = {top: 20, right: 60, bottom: 100, left: 20};
var width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
var xScale = d3.scaleUtc()
.range([0,width])
var yScale = d3.scaleLinear()
.range([height, 0])
var xAxis = d3.axisBottom(xScale)
.tickSize(-height);
var parseDate = d3.utcParse("%Y"),
formatDate = d3.utcFormat("%Y");
var yAxis = d3.axisRight(yScale)
.tickSize(-width)
.tickFormat(d3.format("$,"))
var incomeLine = d3.line()
.curve(d3.curveCatmullRom)
.x(function(d) { return xScale(d.year); })
.y(function(d) { return yScale(d.val); })
var svg = d3.select("#chart-container").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 + ")");
svg.append("rect")
.attr("class", "background")
.attr("height", height)
.attr("width", width)
d3.csv("incomes.csv", function(error, data) {
if (error) return console.warn(error);
console.log(data);
data.forEach(function(d) {
d.val = +d.val;
d.year = parseDate(d.year);
})
var medianData = data.filter(function(d) { return d.cutoff == 'cop50' })
var nestedMedianData = d3.nest()
.key(function(d) { return d.country; })
.entries(medianData)
var usData = nestedMedianData.filter(function(d) { return d.key == 'United States'; })
xScale.domain(d3.extent(data, function(d) { return d.year; }))
yScale.domain(d3.extent(usData[0].values, function(d) { return d.val; })).nice()
var countryButtons = d3.select("#countryButtons")
.selectAll(".buttons")
.data(nestedMedianData)
.style("opacity", 1)
.enter().append("button")
.text(function(d) { return d.key; })
.on("click", function(d) { updateChart(d.values); })
// function that updates the chart when a button is clicked (invoked right above!)
function updateChart(dataset) {
// updating the y-scale domain
yScale.domain(d3.extent(dataset, function(d) { return d.val; })).nice()
// selecting all the dots and binding the new dataset
var dotUpdate = svg.selectAll(".dots")
.data(dataset, function(d) { return d.year });
// updating the positions of the existing dots
dotUpdate.transition()
.style("fill","orange")
.attr("cx", function(d) { return xScale(d.year); })
.attr("cy", function(d) { return yScale(d.val); })
.style("stroke-width", 1.5)
.style("stroke-dasharray", 0)
.style("opacity", 1)
// appending the new dots
dotUpdate.enter().append("circle")
.attr("class","dots")
.attr("r", 5)
.transition()
.style("fill","#00B8A9")
.attr("cx", function(d) { return xScale(d.year); })
.attr("cy", function(d) { return yScale(d.val); })
// handles old dots that no longer have data bound to it
dotUpdate.exit()
.style("fill","#F6416C")
.transition()
.duration(2000)
.remove();
// updates the path, our curvy line
svg.select(".incomeLine")
.datum(dataset)
.transition()
.duration(2200)
.attr("d", incomeLine)
.style("stroke-dasharray", ("3, 3"))
// updates the y axis since its different for each country
svg.select(".y")
.transition()
.duration(2000)
.call(yAxis)
}
d3.select(window).on("resize", resizeChart);
function resizeChart() {
var margin = {top: 20, right: 60, bottom: 100, left: 20};
var width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
xScale.range([0,width])
yScale.range([height, 0])
xAxis.tickSize(-height);
yAxis.tickSize(-width);
var svg = d3.select("#chart-container").select("svg"),
g = svg.select("g");
svg.transition()
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
g.transition()
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.select(".background")
.transition()
.attr("height", height)
.attr("width", width)
// updating the positions of the existing dots
g.selectAll(".dots")
.transition()
.style("fill","#FFDE7D")
.attr("cx", function(d) { return xScale(d.year); })
.attr("cy", function(d) { return yScale(d.val); })
// updates the path, our curvy line
g.select(".incomeLine")
.transition()
.ease(d3.easePoly)
.style("stroke-dasharray", ("3, 3"))
.attr("d", incomeLine)
// updates the y axis since its different for each country
g.select(".y")
.transition()
.attr("transform","translate(" + width + ",0)")
.call(yAxis)
// updates the y axis since its different for each country
g.select(".x")
.transition()
.attr("transform","translate(0," + height + ")")
.call(xAxis)
}
svg.append("g")
.attr("class", "y axis")
.attr("transform","translate(" + width + ",0)")
.call(yAxis)
svg.append("g")
.attr("class", "x axis")
.attr("transform","translate(0," + height + ")")
.call(xAxis)
svg.selectAll(".dots")
.data(usData[0].values, function(d) { return d.year })
.enter().append("circle")
.attr("class","dots")
.attr("cx", function(d) { return xScale(d.year); })
.attr("cy", function(d) { return yScale(d.val); })
.attr("r", 5)
svg.append("path")
.datum(usData[0].values)
.attr("class", "incomeLine")
.attr("d", incomeLine)
});
</script>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-color.v1.min.js
https://d3js.org/d3-dispatch.v1.min.js
https://d3js.org/d3-ease.v1.min.js
https://d3js.org/d3-interpolate.v1.min.js
https://d3js.org/d3-selection.v1.min.js
https://d3js.org/d3-timer.v1.min.js
https://d3js.org/d3-transition.v1.min.js