Skip to content

Instantly share code, notes, and snippets.

@uafrazier
Last active September 13, 2019 10:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save uafrazier/cf3d14c24a82e5f7b18d to your computer and use it in GitHub Desktop.
Save uafrazier/cf3d14c24a82e5f7b18d to your computer and use it in GitHub Desktop.
D3: Multi-Line Chart
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>US Passports 1996-2014</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
<style type="text/css">
body {
background:#24263F;
font-family: 'Open Sans',Helvetica,arial,sans-serif;
}
h1 {
font-weight: 600;
text-transform: uppercase;
}
header {
color: #F4D73C;
}
hr {
border: 2px solid #F4D73C;
margin-top: 20px;
margin-left: 10px;
margin-right: 10px;
}
a {
color: #F4D73C;
text-decoration: underline;
}
svg {
background: #24263F;
float:left;
}
.axis path,
.axis line {
fill: none;
stroke: #F4D73C;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
fill: #F4D73C;
}
img {
float:left;
height: 100px;
width: 100px;
margin-right: 10px;
margin-left: 10px;
}
.explanatory {
color: #F4D73C;
font-size: 14px;
padding: 10px 25px 0 0;
margin: 25px 25px 225px 88px;
}
.legend {
text-transform: uppercase;
}
</style>
</head>
<body>
<header>
<img src="http://joshuafrazier.info/images/seal.png">
<h1>United States Passports</h1>
<p>Applications and Issuances: 1996-2014 (Fiscal Years).<br /> Source: <a href="http://travel.state.gov/content/passports/english/passports/statistics.html">Bureau of Consular Affairs</a></p>
</header>
<hr>
<script type="text/javascript">
//Dimensions and padding
var w = 1000;
var h = 500;
var padding = [ 20, 10, 50, 100 ]; //Top, right, bottom, left
//Set up date formatting and years
var dateFormat = d3.time.format("%Y");
//Set up scales
var xScale = d3.time.scale()
.range([ padding[3], w - padding[1] - padding[3] ]);
var yScale = d3.scale.linear()
.range([ padding[0], h - padding[2] ]);
//Configure axis generators
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(20)
.tickFormat(function(d) {
return dateFormat(d);
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
//Configure line generator
var line = d3.svg.line()
.x(function(d) {
return xScale(dateFormat.parse(d.year));
})
.y(function(d) {
return yScale(d.numbers);
});
//Create the empty SVG image
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Load passport issued data
d3.csv("passports_issued.csv", function(issuedData) {
//Load passport application data
d3.csv("passport_applications.csv", function(appliedData) {
//Create a new array that contains both the
//applied for and issued data, merged into one
var mergedData = issuedData.concat(appliedData);
//console.log(mergedData);
//Use the newly merged data to determine the
//min and max values, for setting scale domains
xScale.domain([
d3.min(mergedData, function(d) {
return dateFormat.parse(d.year);
}),
d3.max(mergedData, function(d) {
return dateFormat.parse(d.year);
})
]);
yScale.domain([
d3.max(mergedData, function(d) {
return +d.numbers;
}),
0
]);
//Lines
//
// Note data is wrapped in another array, so all its
// values are bound to a single element (the line!)
//
svg.data([ issuedData ])
.append("path")
.attr("class", "line issued")
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "#ff6666")
.attr("stroke-width", 2);
svg.data([ appliedData ])
.append("path")
.attr("class", "line applied")
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "#FFFFFF")
.attr("stroke-width", 2);
//Axes
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding[2] + 10) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (padding[3] - 10) + ",0)")
.call(yAxis);
});
//End passports applied for data load function
});
//End passports issued data load function
//legend
svg.append("text")
.attr("x",w-225)
.attr("y", h-125)
.attr("class", "legend")
.style("fill", "#FFFFFF")
.text("Applications");
svg.append("text")
.attr("x",w-225)
.attr("y", h-100)
.attr("class", "legend")
.style("fill", "#ff6666")
.text("Issuances");
//explanatory
var para = d3.select("body")
.append("p")
.attr("class", "explanatory")
.html("1997-2007: the number of passports applied for and issued more than tripled.<br/><br/>2001: after the World Trade Center attacks the gap between applications and issuances gets larger, possibly indicating stricter legal requirements or more stringent adjudication. <br/><br/>2007: the <a href='https://en.wikipedia.org/wiki/Western_Hemisphere_Travel_Initiative'> Western Hemisphere Travel Initiative</a> was implemented requiring travelers to show a valid passport or other approved document when traveling to the US from areas within the Western Hemisphere.<br/><br/>2008: passport cards were introduced. One application can be used for a passport book and a passport card thus allowing for the total number of issuances (books and cards) to exceed the number of applications.");
</script>
</body>
</html>
year numbers
1996 5531268
1997 6330968
1998 6557987
1999 6801129
2000 7367472
2001 7182304
2002 7217320
2003 7355537
2004 9046790
2005 10412146
2006 12333428
2007 18581977
2008 16054336
2009 14045147
2010 14005102
2011 12028710
2012 12481013
2013 12673903
2014 13287573
year numbers
1996 5547693
1997 6295003
1998 6539864
1999 6722198
2000 7292182
2001 7119506
2002 7001482
2003 7300667
2004 8825410
2005 10123424
2006 12133537
2007 18382798
2008 16132536
2009 14170171
2010 14794604
2011 12613153
2012 13125829
2013 13529757
2014 14087341
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment