xxxxxxxxxx
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="spinner.css">
<style type="text/css">
body {
background: #ffffff;
/*transform: scale(1.05);*/
}
svg {
overflow: visible;
/*margin-bottom:50px;*/
/*border:1px solid pink;*/
}
h2 {
font-family: sans-serif;
text-align:center;
font-size: 13px;
margin-left:15px;
}
h3 {
font-size:9px;
font-family: sans-serif;
text-align:center;
margin-left:15px;
text-transform: uppercase;
font-weight: 100;
}
div.wrapper {
width:1050px;
margin: 0 auto;
position:relative;
}
div.description {
width:650px;
position:absolute;
top:15px;
left:15px;
/*margin:10px auto;*/
display:none;
z-index: 10000;
}
div.description p {
color: #666;
font-size:13px;
font-family: sans-serif;
margin-bottom:30px;
}
div.description p a {
color: teal;
}
div.container {
width: 1050px;
height: 450px;
margin: 50px auto;
}
div.intro {
font-size: 13px;
font-family: sans-serif;
text-align: center;
}
div.cutoff-container {
display:inline-block;
margin-right:20px;
}
.country-line {
fill: none;
stroke: #dedede;
stroke-width:2px;
}
.country-line.hover {
/*stroke-width:3px;*/
stroke: #666;
}
.country-line.united-states {
stroke: #885ead;
stroke-width:3px;
}
path.domain {
fill:none;
}
.axis {
font-family: sans-serif;
}
.x.axis text {
font-size:12px;
fill: #888;
}
.y.axis text {
fill: none;
font-size:12px;
}
.x.axis path.domain{
stroke-width:1px;
stroke: #222;
}
.last-y-axis text{
fill: #888 !important;
}
.tick line{
fill: none;
stroke: #888;
stroke-dasharray: 2px 3px;
shape-rendering: crispEdges;
stroke-width: 1px;
opacity:.75;
}
label {
font-family: sans-serif;
font-size: 13px;
font-weight: 200;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Chrome/Safari/Opera */
-khtml-user-select: none; /* Konqueror */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none;
}
h1 {
font-family: serif;
line-height: 30px;
font-size: 26px;
font-weight:200;
}
h4 {
font-family: sans-serif;
font-size:16px;
margin:-10px 0 10px 0;
}
span.legend-bar{
width: 40px;
height:3px;
background:#666;
display:inline-block;
margin-right:10px;
position:relative;
top:-3px;
}
div.legend ul li {
margin-bottom:10px;
}
div.legend ul li span.text {
font-size:16px;
font-family: sans-serif;
font-weight: 200;
}
div.legend ul {
list-style: none;
margin:30px 0;
padding:0;
}
li.row {
display:none;
}
li.row.show {
display:block;
}
span.legend-bar.us {
background:#885ead;
}
</style>
<body>
<div class="wrapper">
<div class="description">
<p>The following is a recreation of a visualization by Kevin Quealy <br/>found in <a href="https://www.nytimes.com/2014/04/23/upshot/the-american-middle-class-is-no-longer-the-worlds-richest.html" target="_blank">this</a> article published by the NY Times on April 22, 2014</p>
<h1>American Incomes Are Losing Their Edge, <br/>Except at the Top</h1>
<h4>Inflation-adjusted, after-tax income over time</h4>
<input type="checkbox" id="smooth" />
<label for="smooth">Remove smoothing</label>
<div class="legend">
<ul>
<li><span class="legend-bar us"></span><span class="text">United States</span></li>
<li class="row"><span class="legend-bar hover-legend"></span><span class="text hover-legend">Rest of World</span></li>
</ul>
</div>
</div>
<div class="container">
<div id="cssload-pgloading">
<div class="cssload-loading"></div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script>
var container = d3.select("div.container");
var margin = {top: 20, right: 50, bottom: 25, left: 10};
var width = container.node().getBoundingClientRect().width - margin.left - margin.right - 220,
height = container.node().getBoundingClientRect().height - margin.top - margin.bottom;
var incomeData = false;
var svg =
clean = function(d) {
d.year = +d.year;
d.val = +d.val;
return d;
};
drawChart = function(data){
d3.select("div.description").style("display","block");
container.html("");
var incomeCutoffAndCountry = d3.nest()
.key(function(d) { return d.cutoff; })
.key(function(d) { return d.country; })
.entries(data);
var cutoffContainer = container.selectAll(".cutoff-container")
.data(incomeCutoffAndCountry, function(d) { return d.key; });
cutoffContainer.enter()
.append("div")
.attr("class", function(d) { return "cutoff-container"; })
.style("height", height)
.style("width", width/incomeCutoffAndCountry.length);
cutoffContainer.exit().remove();
var lineWidth = width/incomeCutoffAndCountry.length;
var xScale = d3.scale.linear()
.range([0, lineWidth])
.domain([1980,2010]);
var yScale = d3.scale.linear()
.range([height,0])
.domain([0, 80000]);
var line = d3.svg.line()
.x(function(d) { return xScale(d.year); })
.y(function(d) { return yScale(d.val); });
var svg = cutoffContainer.append("svg")
.attr("width", lineWidth)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("right")
.tickFormat(d3.format("$,"))
.innerTickSize(lineWidth)
.outerTickSize(0)
.tickValues(function(d){
return [10000,20000,30000,40000,50000,60000,70000,80000];
});
var dateFormat = d3.time.format("%y");
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickValues(function(d){
return [1980,2010];
})
.tickFormat(function(d){
return "'"+(""+d).substring(2);
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,"+(height+5)+")")
.call(xAxis);
var y = svg.append("g")
.attr("class", "y axis")
.classed("last-y-axis", function(d){
return d.key==="cop95";
})
.attr("width", lineWidth)
.call(yAxis);
var numLinesByIndex = [1,1,2,2,2,2,3,4,5,6,8];
y.selectAll("g.tick").forEach(function(d,i){
d.forEach(function(l,j){
if( (j+1) > numLinesByIndex[i] ) {
l.remove();
}
})
});
var countryLines = svg.selectAll(".country-line")
.data(function(d){ return d.values; }, function(d){ return d.key; });
countryLines.enter()
.append("path")
.attr("class", function(d){ return "country-line " + d.key.replace(" ","-").toLowerCase(); })
.attr("d", function(d) {
var values = smoothLines ? [d.values[0],d.values[d.values.length-1]] : d.values;
return line(values);
})
.on('mouseover',function(d){
// console.log(d);
d3.select("span.text.hover-legend ").html(d.key);
d3.select("li.row").classed("show",true);
d3.selectAll("."+this.className.baseVal.replace(" ","."))
.classed("hover",true);
d3.selectAll(".hover")
.each(function(){
this.parentElement.appendChild(this);
});
})
.on('mouseout',function(){
d3.select("span.text.hover-legend ").html("Rest of World");
d3.select("li.row").classed("show",false);
d3.selectAll(".hover")
.classed("hover",false);
d3.selectAll(".united-states")
.each(function(){
this.parentElement.appendChild(this);
});
});
countryLines.exit().remove();
cutoffContainer.append("h2")
.text(function(d){
return d.key=='cop50' ? "Median" : d.key.substring(3) + "th";
});
cutoffContainer.append("h3")
.text("percentile")
.style("color", function(d){
return d.key=='cop50' ? "white" : "#333"
});
};
var smoothLines = true;
ready = function(err, data) {
d3.selectAll("#smooth").on("change", function() {
smoothLines = !this.checked;
drawChart(data);
});
d3.select("#cssload-pgloading").remove();
drawChart(data);
};
d3.csv("incomes.csv", clean, ready);
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js