Skip to content

Instantly share code, notes, and snippets.

@cerico
Last active July 21, 2019 13:38
Show Gist options
  • Save cerico/9b23469eb1d72b6fc73feb8ae3e07b3e to your computer and use it in GitHub Desktop.
Save cerico/9b23469eb1d72b6fc73feb8ae3e07b3e to your computer and use it in GitHub Desktop.
Multi Area Chart with time axis
license: mit
iyear Belgium Denmark France Germany Greece Ireland Italy Luxembourg Netherlands Portugal Spain United Kingdom
1970 0 0 0 0 2 1 0 0 0 0 0 20
1971 0 0 0 0 0 1 0 0 0 0 0 110
1972 0 0 1 0 0 6 1 0 0 0 2 368
1973 0 0 5 0 5 4 62 0 1 0 6 210
1974 0 0 3 0 92 34 26 0 1 0 19 234
1975 0 0 3 0 1 7 0 0 4 0 31 245
1976 0 0 7 0 14 5 10 0 0 3 17 264
1977 0 0 3 0 1 2 25 0 9 0 44 103
1978 1 0 21 0 0 1 21 0 1 0 84 81
1979 1 0 11 0 1 9 24 0 3 3 112 133
1980 2 0 20 0 5 12 125 0 0 3 116 115
1981 6 0 8 0 3 2 24 0 0 2 39 86
1982 0 0 17 0 2 2 12 0 0 3 42 95
1983 2 0 19 0 4 5 2 0 0 8 42 77
1984 0 0 15 0 5 1 23 0 0 3 51 69
1985 10 1 17 0 64 2 19 0 0 1 70 64
1986 0 0 25 0 6 0 1 0 0 1 57 63
1987 1 0 5 0 2 6 3 0 0 0 64 104
1988 1 0 6 0 14 0 6 0 4 2 25 372
1989 4 0 3 0 4 3 0 0 0 1 29 66
1990 2 0 3 0 2 0 0 0 2 0 32 77
1991 1 0 6 10 15 3 0 0 0 0 46 88
1992 1 1 9 17 2 0 17 0 0 0 29 94
1993 2 0 5 27 0 1 14 0 0 0 19 3
1994 0 0 7 2 3 4 2 0 0 2 17 66
1995 0 0 19 10 0 1 0 0 1 0 18 11
1996 0 0 18 1 0 1 0 0 0 0 5 15
1997 4 0 0 0 1 0 0 0 6 0 11 23
1998 0 0 1 0 0 1 0 0 0 0 6 45
1999 0 0 0 3 1 0 1 0 0 0 0 7
2000 0 0 4 1 1 0 0 0 0 0 29 7
2001 0 0 0 3 0 0 0 0 0 0 14 8
2002 0 0 0 0 0 0 1 0 1 0 5 2
2003 0 0 0 0 0 0 0 0 0 0 3 2
2004 0 0 0 1 0 0 1 0 1 0 193 0
2005 0 0 0 2 0 0 1 0 0 0 0 57
2006 0 0 1 2 0 1 0 0 0 0 2 0
2007 0 0 3 1 0 0 0 0 0 0 0 4
2008 0 0 0 0 0 0 0 0 0 0 3 0
2009 0 0 0 0 1 0 0 0 7 0 3 3
2010 0 0 0 0 4 0 0 0 0 0 0 0
2011 0 0 0 2 0 1 0 0 0 0 0 1
2012 1 0 8 0 0 0 0 0 0 0 0 1
2013 0 0 0 0 2 0 0 0 0 0 0 4
2014 4 0 1 0 0 0 0 0 0 0 0 0
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="//fonts.googleapis.com/css?family=.|Oswald:light,normal,bold|Oswald:light,normal,bold|Oswald:light,normal,bold|Raleway:light,normal,bold|Roboto:light,normal,bold" rel="stylesheet" type="text/css" />
<style>
body { color:#3288e2;background:#fbf7ef;margin:0;top:0;right:0;bottom:0;left:0; }
svg {
font: 10px sans-serif;
}
.orange {
fill: black
}
.normal{
opacity: 0.1
}
.highlighted {
opacity: 1
}
.rect {
background:#3288e2;
width: 50px;
height: 50px
}
.line {
fill: none;
stroke: #3288e2;
/* stroke-width: 2px; */
}
.title {
font-family: Raleway;
text-align: center;
margin-top: 3%;
font-weight: 600;
font-size: 22px;
letter-spacing: 0.15em;
}
.container {
background: #ece5d6;
margin-right: 5%;
margin-left: 5%;
margin-top: 24px;
margin-bottom: 24px;
text-align: center;
padding-bottom: 24px;
padding-top: 24px;
overflow: scroll;
}
.todos {
border: 2px solid #ece5d6;
text-align: left;
font-family: roboto;
margin-top: 16px;
padding-left: 5%;
padding-right: 5%;
}
.todo {
line-height: 24px;
background: #3288e2;
color: #fbf7ef;
padding-top: 0%;
padding-left: 2%;
font-family: raleway;
width: 50%;
}
.first {
padding-top:8px
}
.last {
padding-bottom:8px
}
.label {
width: 8%;
height: 36px;
padding-top: 4px;
display: inline-block;
margin-right: 2%;
margin-left: 2%;
text-align: center;
color: #636363;
font-family: 'Oswald';
font-size: 21px;
min-width: 74px;
margin-bottom: 18px;
}
.visualization {
text-align:left
}
.legend{
color: red
}
</style>
</head>
<body>
<div class="title">EU Terrorism 1970-2014</div>
<div class="container">
<div class="legend"></div>
<div class="visualization"></div>
<div class="todos">
<div class="first todo">1. Redo the transition to add/remove with d3</div>
<div class="todo">2. Work out how to redraw axis</div>
<div class="todo">3. Group numbers by decade</div>
<div class="todo">4. Transition the opacity</div>
<div class="todo">5. Sort the lines to put the smaller ones first</div>
<div class="todo">6. Get different date (EU Migration?) at click of button</div>
<div class="last todo">7. Responsive width</div>
</div>
</div>
<script>
//country colours
var colours = {
Spain: '#f7ecab',
Italy: '#96dfd1',
UnitedKingdom: '#f5c8c8',
France:'#badeb5',
Belgium:'#9dbece',
Denmark:'pink',
Germany: 'orange',
Greece: 'green',
Ireland: '#d6ecd8',
Italy: 'yellow',
Luxembourg:'rebeccapurple',
Netherlands:'blue',
Portugal:'red'
}
//Margin Convention
var margin = {top: 20, right: 30, bottom: 20, left: 60},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
labelHeight = 45
//Container
var svg = d3.select(".visualization").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 + ")");
var legend = d3.select(".legend").append("svg")
.attr("width", width)
.attr("height", labelHeight)
.append('g');
//Saving the correct time format for D3
var parseDate = d3.timeParse("%b %Y");
//Saving the correct time format for the axis lables
var formatTime = d3.timeFormat("%b %Y");
//Defining the range for the time scale
var x = d3.scaleTime().range([0, width]);
//Defining the range for the linear scaling
var y = d3.scaleLinear().range([height, 0]);
//Creating the line generator, defing by using accessor functions the date being the x variable and the price being the y variable
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
////Creating the area generator, defing by using accessor functions the date being the x variable and the price being the y1 variable and the height being the y0 in order to avoid that the area that at the left up corner.
var area = d3.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
//Connecting to the belgium set
d3.text('EU_Terrorism.csv', function(error, raw) {
var dsv = d3.dsvFormat(',')
var orig_data = dsv.parse(raw);
var data = [];
orig_data.forEach( function(row) {
Object.keys(row).forEach( function(colname) {
// Ignore 'State' and 'Value' columns
if(colname == "iyear" || colname == "price") {
return
}
data.push({"date": row["iyear"], "price": row[colname], "country": colname});
});
});
var symbols = d3.nest()
.key(function(d) { return d.country; })
.entries(data);
// Parse and caculate some values for each countries
symbols.forEach(function(s) {
s.key = s.key.replace(/\s+/g, '');
// changes eg "United Kingdom to UnitedKingdom"
s.colour = colours[s.key]
s.values.forEach(function(d) {
d.date = d.date;
d.price = +d.price;
});
s.maxPrice = d3.max(s.values, function(d) { return d.price; });
s.sumPrice = d3.sum(s.values, function(d) { return d.price; });
});
console.table(orig_data)
console.table(data)
//Defining the domain for the linear scaling using D3 extent which return the min and max
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(symbols.map(function(d) { return d.maxPrice; }))])
svg.selectAll(".line")
.data(symbols)
.enter()
.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return (d.colour); });
svg.selectAll(".area")
.data(symbols)
.enter()
.append("path")
.attr("class", "normal")
.attr("id", function(d) { return (d.key); })
.attr("d", function(d) { return area(d.values); })
.style("class", "normal")
.style("fill", function(d) { return (d.colour); });
// Calling and defining the x axis at the same time
svg.append("g")
.attr("class", "axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.ticks(8)
.tickFormat(formatTime));
//Calling and defining the y axis at the same time
svg.append("g")
.attr("class", "axis--y")
.call(d3.axisLeft(y)
.ticks(4));
// Legend
legend.selectAll("rect")
.data(symbols)
.enter()
.append("g")
.append("rect")
.attr("height", labelHeight)
.attr("width", width / symbols.length)
.attr("fill", function(d) { return (d.colour); })
.attr("transform", function(d, i){
return "translate(" + (width / symbols.length*i) + ",0)"
});
legend.selectAll("g")
.append("text")
.attr("transform",
function(d, i){ return "translate(" + (width / symbols.length*i) + ",30)";
})
.attr("font-size", "2em")
.attr("color", "black")
.text(function(d){ return d.key;})
.on("click", function(d) {
var opacity = d3.selectAll(`#${d.key}`).attr('class') === 'normal' ? 'highlighted' : 'normal'
d3.selectAll(`#${d.key}`).attr('class', opacity)
});
})
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment