Skip to content

Commit 3bdd939

Browse files
alansmithyalansmithy
alansmithy
authored and
alansmithy
committedJun 9, 2016
add-priestley-timeline
Added a simple Priestley timeline to accompany June Chart Doctor feature
1 parent af5bfc2 commit 3bdd939

File tree

6 files changed

+196
-1
lines changed

6 files changed

+196
-1
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# chart-doctor
2-
Sample files to accompany the FT's Chart Doctor column
2+
Sample files to accompany the [FT Chart Doctor](http://www.ft.com/chart-doctor) column.

‎priestley-timeline/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#Joseph Priestley timeline
2+
3+
This sample uses the data visualisation library d3.js to create a timeline of dates and durations similar to those popularised by [Jospeh Priestley](https://en.wikipedia.org/wiki/Joseph_Priestley) in the 18th century.
4+
5+
It takes as its input the datafile [composers.csv](composers.csv) which simply contains the name of a composer, along with birth and death date.
6+
7+
![Priestley-style timeline of great composers](images/priestley.png)
8+
9+
For more information, please visit the [FT Chart Doctor](http://www.ft.com/chart-doctor)

‎priestley-timeline/composers.csv

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name,born,died
2+
Haydn,31/03/1732,31/05/1809
3+
Mozart,27/01/1756,05/12/1791
4+
Beethoven,17/12/1770,26/03/1827
5+
Mendelssohn,03/02/1809,04/11/1847
6+
Schumann,08/06/1810,29/07/1856
7+
Schubert,31/01/1797,19/11/1828
8+
Berlioz,11/12/1803,08/03/1869
9+
Bizet,25/10/1838,03/06/1875
10+
Bruckner,04/09/1824,11/10/1896
11+
Brahms,07/05/1833,03/04/1897
12+
Elgar,02/06/1857,23/02/1934
63 KB
Loading

‎priestley-timeline/index.html

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<html>
2+
<head>
3+
<title>Basic Priestley-style timeline</title>
4+
<style>
5+
/*some basic CSS*/
6+
.axis path{fill:none;stroke:none}
7+
.axis line{fill:none;stroke:gray;stroke-width:1px;}
8+
.axis text{fill:gray;stroke:none;}
9+
text {text-anchor:middle}
10+
</style>
11+
</head>
12+
<body>
13+
<h1>A Specimen of a Priestley-style Timeline</h1>
14+
<script src="js/d3.min.js"></script>
15+
<script>
16+
17+
var file="composers.csv"
18+
var width=600,height=400;
19+
var margin={top:50,bottom:30,left:20,right:20}
20+
21+
//create svg element to hold graphics
22+
var svg=d3.select("body").append("svg")
23+
.attr("width",width)
24+
.attr("height",height)
25+
26+
//load the data
27+
d3.csv(file,function(data){
28+
29+
//define the date format used in the data
30+
var parseDate = d3.time.format("%d/%m/%Y");
31+
//parse the date information in the data
32+
data.forEach(function(d) {
33+
d.born=parseDate.parse(d.born)
34+
d.died=parseDate.parse(d.died)
35+
});
36+
37+
//sort the lifespans into date-of-birth order - we will use this for the drawing order of the chart
38+
data.sort(function(a, b){
39+
return a.born-b.born;
40+
});
41+
42+
//find out the range of the dates
43+
//first birth
44+
var minDate=d3.min(data, function(d){
45+
return d.born;
46+
})
47+
48+
//last death
49+
var maxDate=d3.max(data, function(d){
50+
return d.died;
51+
})
52+
53+
//calculate plot dimensions
54+
var plotWidth = width-(margin.left+margin.right)
55+
var plotHeight = height-(margin.top+margin.bottom)
56+
57+
//create a scale for the timeline
58+
var xScale = d3.time.scale()
59+
.domain([minDate,maxDate])
60+
.range([0,plotWidth])
61+
62+
//a scale for vertical arrangement of each lifespan
63+
var yScale = d3.scale.ordinal()
64+
.domain(data.map(function(d){
65+
return d.name;
66+
}))
67+
.rangeRoundBands([0,plotHeight],0.6);
68+
69+
//define the chart's time axes
70+
//primary axis - these will be labelled
71+
var xAxis = d3.svg.axis()
72+
.scale(xScale)
73+
.orient("bottom")
74+
.ticks(4)
75+
.tickSize(-plotHeight)
76+
77+
//secondary axis - more ticks but no labels
78+
var xAxis2 = d3.svg.axis()
79+
.scale(xScale)
80+
.orient("bottom")
81+
.tickFormat(d3.time.format(""))
82+
.ticks(20)
83+
84+
//draw the axes
85+
svg.append("g")
86+
.attr("class","axis")
87+
.attr("transform","translate("+margin.left+","+(margin.top+plotHeight)+")")
88+
.call(xAxis)
89+
svg.append("g")
90+
.attr("class","axis")
91+
.attr("transform","translate("+margin.left+","+(margin.top+plotHeight)+")")
92+
.call(xAxis2)
93+
94+
//offset the textlabels
95+
svg.selectAll(".axis text")
96+
.attr("dy",20)
97+
98+
//create chart geometry
99+
//chart group
100+
var chart = svg.append("g")
101+
.attr("id","chart")
102+
.attr("transform","translate("+margin.left+","+margin.top+")")
103+
104+
//a row for each lifespan
105+
var rowGroups = chart.append("g")
106+
.attr("id","chart_rows")
107+
.selectAll("g")
108+
.data(data)
109+
.enter()
110+
.append("g")
111+
.attr("transform",function(d,i){
112+
return "translate(0,"+yScale(d.name)+")"
113+
})
114+
115+
rowGroups.each(function(d,i){
116+
//create a rectangle to show time between birth and and death
117+
d3.select(this).append("rect")
118+
.attr("x",function(d){
119+
return xScale(d.born)
120+
})
121+
.attr("width",function(d){
122+
return xScale(d.died)-xScale(d.born)
123+
})
124+
.attr("height",yScale.rangeBand)
125+
.attr("fill","black")
126+
.attr("fill-opacity",0.8)
127+
128+
//create a label with each composer's name on it - put it in middle of lifespan
129+
d3.select(this).append("text")
130+
.attr("x",function(d){
131+
//calculate mid point of composer's life
132+
var midPoint = new Date((d.born.getTime() + d.died.getTime()) / 2);
133+
return xScale(midPoint)
134+
})
135+
.attr("y",function(d){
136+
return -1;
137+
})
138+
.text(function(d){
139+
return d.name
140+
})
141+
142+
//label the first row with a key
143+
if (i==0){
144+
var key = d3.select(this).append("g")
145+
.attr("class","axis")
146+
key.append("text")
147+
.attr("x",function(d){
148+
return xScale(d.born);
149+
})
150+
.attr("y",function(d){
151+
return -5;
152+
})
153+
.text("born")
154+
key.append("text")
155+
.attr("x",function(d){
156+
return xScale(d.died);
157+
})
158+
.attr("y",function(d){
159+
return -5;
160+
})
161+
.text("died")
162+
}
163+
})//end each row
164+
165+
})//end
166+
167+
</script>
168+
</body>
169+
</html>

‎priestley-timeline/js/d3.min.js

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.