The D3.js code that I used as the base for the Criminality New Year’s card that I designed. You can see the end result of all 4 cards and read about the design process in my blog Saying “Happy new year” with data
You can find the design of the two other cards here
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #F7F7F7;
shape-rendering: crispEdges;
}
.axis path {
display: none;
}
.line, .lineNL {
fill: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 60, right: 80, bottom: 60, left: 80},
width = 900 - margin.left - margin.right,
height = 460 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
.domain([2005,2014]);
var y = d3.scale.linear()
.range([height, 0])
.domain([40,140]);
var greenColors = ["#769D0C", "#89B41C", "#50972F", "#356B13", "#466100"];
var redColors = ["#CE6B5D","#941F1F","#7F0000","#CC0000","#8C0000"];
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.format("d"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width, 0, 0);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d) { return x(d.year); })
.y(function(d) { return y(d.region); });
var svg = d3.select("body").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.csv("criminality.csv", function(error, data) {
if (error) throw error;
var keys = d3.keys(data[0]).filter(function(key) { return key !== "year"; });
var regionLines = keys.map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
year: +d.year,
region: +d[name]};
})
};
});
//Append axes
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
//Append the region lines
var lines = svg.selectAll(".lines")
.data(regionLines.filter(function(d) {
return d.name !== "Nederland";
}))
.enter().append("g")
.attr("class", "lines");
//Append some random circles
var circles = svg.selectAll(".circles")
.data(data)
.enter().append("g")
.attr("class", "circles");
keys.forEach(function(key) {
circles.append("circle")
.attr("class", "circleRegion")
.attr("cx", function(d) {
return x(d.year) + randomFloat(-25,25);
})
.attr("cy", function(d) {
return y(d[key]) + randomFloat(-25,25);
})
.attr("r", function(d) {
return Math.round( randomFloat(2,10) );
})
.style("fill", function(d) {
return greenColors[randomIntFromInterval(0,greenColors.length-1)];
})
.style("opacity", function(d) {
return randomFloat(0.05,0.3);
});
});
//Place all regions except the Netherlands as a whole
lines
.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke-width", 14)
.style("stroke", function(d) {
return greenColors[randomIntFromInterval(0,greenColors.length-1)];
})
.style("opacity", 0.05);
lines
.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke-width", 4)
.style("stroke", function(d) {
return greenColors[randomIntFromInterval(0,greenColors.length-1)];
})
.style("opacity", 0.1);
lines
.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke-width", 1)
.style("stroke", function(d) {
return greenColors[randomIntFromInterval(0,greenColors.length-1)];
})
.style("opacity", 0.3);
// //Add labels
// lines.append("text")
// .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
// .attr("transform", function(d) {
// return "translate(" + x(d.value.year) + "," + y(d.value.region) + ")";
// })
// .attr("x", 3)
// .attr("dy", ".35em")
// .text(function(d) { return d.name; });
//Place some random circles around the Netherlands line
circles.append("circle")
.attr("class", "circleNL")
.attr("cx", function(d) {
return x(d.year) + randomFloat(-25,25);
})
.attr("cy", function(d) {
return y(d["Nederland"]) + randomFloat(-25,25);
})
.attr("r", function(d) {
return randomFloat(2,12);
})
.style("fill", function(d) {
return redColors[randomIntFromInterval(0,redColors.length-1)];
})
.style("opacity", function(d) {
return randomFloat(0.4,0.8);
});
//Place the Netherlands as a total line on top
var lineNL = svg.selectAll(".linesNL")
.data(regionLines.filter(function(d) {
return d.name === "Nederland";
}))
.enter().append("g")
.attr("class", "linesNL");
lineNL
.append("path")
.attr("class", "lineNL")
.attr("d", function(d) { return line(d.values); })
.style("stroke","#CE6B5D")
.style("opacity", 0.3)
.style("stroke-width", 18);
lineNL
.append("path")
.attr("class", "lineNL")
.attr("d", function(d) { return line(d.values); })
.style("stroke","#CE6B5D")
.style("opacity", 0.5)
.style("stroke-width", 10);
lineNL
.append("path")
.attr("class", "lineNL")
.attr("d", function(d) { return line(d.values); })
.style("stroke", "#941F1F")
.style("stroke-width", 3);
});
function randomFloat(min, max) {
return Math.random() * (min - max) + max;
}
function randomIntFromInterval(min,max) {
return Math.floor(Math.random()*(max-min+1)+min);
}
</script>
year,Nederland,Noord-Nederland,Oost-Nederland,Midden-Nederland,Noord-Holland,Amsterdam,Den Haag,Rotterdam,Zeeland - West-Brabant,Oost-Brabant,Limburg
2005,82.7,61.4,70.4,89.2,78.1,130,85.2,93.4,79.7,83.7,86.8
2006,80.3,61.1,67.5,88.2,76.4,128.8,81.7,90.3,76.6,80.3,83.8
2007,79.7,61.3,65.8,85.4,75,125.6,85.5,88.9,78.2,79.4,83.7
2008,77.9,60.1,63.8,82.9,70.3,122.1,85.6,89.3,75.6,77.8,82.1
2009,76.1,59.8,63.4,76.2,71.7,117.5,81.1,87,76.9,76.6,80.8
2010,72.1,55.7,60.7,71.9,70.4,116.7,81,77,69.9,70.5,75.8
2011,71.7,54.8,59.9,69.1,69.1,117.6,80,81.5,68.9,69.4,76.8
2012,68,52.4,57.4,65.2,64.2,112.9,73.6,75.9,66.8,67.5,72.9
2013,64.8,49.6,54.3,62.9,62,111.5,68.5,72.1,61.4,65.8,68.5
2014,59.8,45.8,48.7,58.2,57.5,103.6,63.7,66.7,57.3,59.5,65.7