Skip to content

Instantly share code, notes, and snippets.

@HarryStevens
Last active Oct 31, 2016
Embed
What would you like to do?
Playfair Import-Export Chart
license: gpl-3.0
height: 530
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- meta -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<!-- fonts -->
<link href="https://fonts.googleapis.com/css?family=IM+Fell+English" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=IM+Fell+DW+Pica+SC" rel="stylesheet">
<!-- css -->
<link rel="stylesheet" href="styles.css"
</head>
<body>
<div class="title">CHART of all the IMPORTS and EXPORTS to and from INDIA<br/>From the Year 1996 to 2015 by H. Stevens</div>
<div class="chart"></div>
<div class="title sub">The Divisions at the Bottom, expreſs <b>YEARS</b>, &amp; those on the Right hand, LAKHS of 2015 RUPEES</div>
<div class="source left">A D3 chart based on <a href="https://commons.wikimedia.org/wiki/File:1786_Playfair_-_1_Chart_of_all_the_import_and_exports_to_and_from_England_from_the_year_1700_to_1782.jpg">the work of William Playfair</a><br />Source: <a href="http://www.commerce.nic.in/eidb/">Export Import Data Bank, Indian Commerce Department</a></div>
<div class="source right">Published as the Act directs. 28.<sup>th</sup> Aug.<sup>st</sup> 2016</div>
<!-- js -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="scripts.js"></script>
</body>
</html>
// a function to convert all the numbers into numbers
function types(d){
// loop through all the years in the data
for (var i = 1996;i<2016;i++){
var name = 'y'+i+'to'+(i+1);
d[name] = +(d[name]);
}
return d;
}
$(document).ready(function(){
// define margins and whatnot
var margin = {top: 0, right: 2, bottom: 30, left: 0},
width = 780 - margin.left - margin.right,
height = 390 - margin.top - margin.bottom;
// time formatter
var parseTime = d3.timeParse("%d-%b-%y");
// x scale
var x = d3.scaleTime()
.range([0,width]);
// y scale
var y = d3.scaleLinear()
.range([height,0]);
// x axis
var xAxis = d3.axisBottom().scale(x).tickSizeInner(-height).tickSizeOuter(0).tickPadding(8);
// y axis
var yAxis = d3.axisRight().scale(y).tickSizeInner(-width).tickSizeOuter(0).tickPadding(8);
// line for exports
var lineExport = d3.line()
.x(function(d){ return x(d.date); })
.y(function(d){ return y(d.export); });
// line for imports
var lineImport = d3.line()
.x(function(d){ return x(d.date); })
.y(function(d){ return y(d.import); });
// areas
var areaAboveExport = d3.area()
.x(lineExport.x())
.y0(lineExport.y())
.y1(0);
var areaBelowExport = d3.area()
.x(lineExport.x())
.y0(lineExport.y())
.y1(height);
var areaAboveImport = d3.area()
.x(lineImport.x())
.y0(lineImport.y())
.y1(0);
var areaBelowImport = d3.area()
.x(lineImport.x())
.y0(lineImport.y())
.y1(height);
// create an svg element, append it to the .chart div, and append a g to it
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 + ')');
d3.tsv('total_real.tsv', type, function(error,data){
if (error) throw error;
//extent of the x domain
//the really enormous numbers are to add padding
x.domain([(d3.min(data, function(d){ return d.date-8000000000; })),(d3.max(data, function(d){ return d.date-(-86890000000); }))]);
// y domain. setting the max to export now, and adding some padding
y.domain([0,(d3.max(data, function(d){ return d.import+d.import*.2; }))]);
// append x axis to the svg element
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height +')')
.call(xAxis)
.append('text')
.attr('class','x axis label')
.attr('x',width-margin.right)
.attr('y',15)
.style('text-anchor','end')
.text('Years');
// set the first year of the x axis a little to the left
$('.x.axis g.tick:first-of-type text').attr('x',8.5);
// append y axis to the svg element
svg.append('g')
.attr('class', 'y axis')
.attr('transform','translate(' + width + ',0)')
.call(yAxis)
.append('text')
.attr('x', -34)
.attr('y', 6)
.attr('dy', '.71em')
.attr('class', 'y axis label')
.style('text-anchor', 'end')
.text('Lakhs');
var bottomY = $('.y.axis .tick:first-of-type text').text();
$('.y.axis .tick:first-of-type text').html(bottomY+' &#8377;')
// y axis ticks placement
$('.y.axis .tick text').attr('x',-60).attr('y',-6);
// append a path, or a line, to the svg element, for Imports
svg.append('defs').append('path')
.datum(data)
.attr('id', 'lineimports')
.attr('class', 'line imports')
.attr('transform','translate(0,-2)')
.attr('d', lineImport);
svg.append('text')
.attr('class','line-text')
.attr('id','imports-text')
.attr('transform','translate(0,-5)')
.attr('word-spacing',25)
.append('textPath')
.attr('xlink:href','#lineimports')
.html('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Line Representing Imports into India')
svg.append('use')
.attr('id', 'exports-line')
.attr('xlink:href', '#lineimports');
// append a line that's the same as imports, but just a single line
svg.append('path')
.datum(data)
.attr('class', 'line-thin')
.attr('d', lineImport);
// append a path, or a line, to the svg element, for EXPORTS
svg.append('defs').append('path')
.datum(data)
.attr('id', 'lineexports')
.attr('class', 'line exports')
.attr('transform','translate(0,2)')
.attr('d', lineExport);
svg.append('text')
.attr('class','line-text')
.attr('id','exports-text')
.attr('transform','translate(0,12)')
.attr('word-spacing',50)
.append('textPath')
.attr('xlink:href','#lineexports')
.html('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Line Representing Exports');
svg.append('use')
.attr('id', 'exports-line')
.attr('xlink:href', '#lineexports');
// append a line that's the same as exports, but just a single line
svg.append('path')
.datum(data)
.attr('class', 'line-thin')
.attr('d', lineExport);
// define areas
var defs = svg.append('defs');
defs.append('clipPath')
.attr('id','clip-import')
.append('path')
.datum(data)
.attr('d',areaAboveImport);
defs.append('clipPath')
.attr('id','clip-export')
.append('path')
.datum(data)
.attr('d',areaAboveExport);
// IMPORT IS ABOVE EXPORT
svg.append('path')
.datum(data)
.attr('d', areaBelowImport)
.attr('class','surplus import')
.attr('clip-path', 'url(#clip-export)')
svg.append('text')
.attr('class','line-text')
.attr('id','area-text')
.attr('transform','translate(0,30)')
.attr('word-spacing',25)
.append('textPath')
.attr('xlink:href','#lineimports')
.html('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BALANCE against INDIA')
// EXPORT IS ABOVE IMPORT
svg.append('path')
.datum(data)
.attr('class','surplus export')
.attr('d', areaBelowExport)
.attr('clip-path', 'url(#clip-import)');
// place the shaded area below the axis lines
$('svg g:first-of-type').before($('.import.surplus')).before($('.export.surplus'));
});// end tsv
// set the data types
function type(d) {
d.date = parseTime(d.date);
d.export = +d.export;
d.import = +d.import;
return d;
}
});// end document ready
body {
font-family: 'IM Fell English', serif;
font-size: 16px;
width: 780px;
margin: 0 auto;
display: table;
}
/*TITLES*/
.title {
margin-top: 20px;
width: 100%;
text-align: center;
font-style: italic;
}
.title.sub {
margin-top: 0px;
}
.source {
font-size: .8em;
font-style: italic;
}
.source.left {
float: left;
}
.source.right {
float: right;
}
/*CHART*/
.chart {
margin-top: 20px;
border-top: 2px solid #000;
}
/*LINES*/
.line {
fill: none;
stroke-width: .2em;
}
.line-thin {
fill: none;
stroke-width: .05em;
stroke: #000;
}
.line.exports {
stroke: #b13737;
}
.line.imports {
stroke: #e5bd10;
}
.line-text {
font-size: .8em;
}
#exports-line {
fill: none;
stroke: #000;
}
/*AXES*/
.axis path,
.axis line {
fill: none;
stroke: #888;
shape-rendering: crispEdges;
}
.axis path {
stroke: #000;
stroke-width: .2em;
}
.x.axis path {
display: none;
}
.x.axis g.tick:first-of-type line,.y.axis g.tick:first-of-type line {
stroke: #000;
stroke-width:.2em;
}
.axis.label {
fill: #000;
font-size: 1em;
font-family: 'IM Fell English', serif;
}
.tick text {
font-family: 'IM Fell English', serif;
}
/*AREA*/
.surplus {
fill-opacity: .5;
}
.surplus.import {
fill: #b3e6ff;
}
.surplus.export {
fill: #fdd8d6;
}
#area-text {
font-family: 'IM Fell DW Pica SC', serif;
}
date export import
1-Apr-96 41823925.48 48899720.99
1-Apr-97 42661639.71 50878174.02
1-Apr-98 41227180.05 52607895.99
1-Apr-99 45155981.31 60994547.19
1-Apr-00 54557029.8 61873898.82
1-Apr-01 53299582.1 62525927.17
1-Apr-02 62763768.89 73112644
1-Apr-03 69527918.09 85108515.37
1-Apr-04 85577410.99 114242714.2
1-Apr-05 99499092.78 143969139.9
1-Apr-06 117214752.5 172303793.4
1-Apr-07 126581658.9 195376157.2
1-Apr-08 148813644.7 243275092.4
1-Apr-09 132748781.3 214106480.4
1-Apr-10 165996781.9 245786174.9
1-Apr-11 194972599.5 311946610.9
1-Apr-12 199386830.7 325637758.1
1-Apr-13 209551219.2 298697729.3
1-Apr-14 199116583.3 287394090.3
1-Apr-15 171461770.1 248800746.7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment