Example of sequencing through temporal data using D3.js. Script binds CSV data to geometries at runtime.
Updated from Yet another animated choropleth map ...
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sequenced choropleth map</title>
<style>
#map {
width: 960px;
height: 480px;
margin: 18px auto 0;
background: whitesmoke;
position: relative;
}
#ui {
position: absolute;
left: 8px;
bottom: 8px;
}
#ui output {
padding: 3px 6px;
margin: 0 0 8px 0;
width: 40px;
border: 1px solid gray;
display: block;
text-align: center;
}
#ui input {
width: 280px;
}
.region {
stroke: #fff;
}
</style>
</head>
<body>
<div id="map">
<div id="ui">
<output id="output">2010</output>
<input id="sequence" type='range' min="2010", max="2016", value="2010", step="1" >
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/simple-statistics@4.1.0/dist/simple-statistics.min.js"></script>
<script>
(function(){
var width = 960,
height = 480;
var svg = d3.select("#map")
.append("svg")
.attr("width", width)
.attr("height", height);
var projection = d3.geoConicEqualArea()
.center([0, -29])
.rotate([-24,0])
.scale(2000)
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
// colors from https://github.com/CartoDB/CartoColor/blob/master/cartocolor.js
var colors = ["#f9ddda", "#eda8bd", "#ce78b3", "#9955a8", "#573b88"];
// function to take a number and output a color
var colorize = d3.scaleThreshold()
.range(colors);
d3.queue()
.defer(d3.json, 'sa.json')
.defer(d3.csv, 'data.csv')
.await(processData);
function processData(err, geoms, dataSet){
// empty array for holding all values for later
// classifying data
var dataValues = [];
// loop through your geometry features
geoms.features.forEach(function(geom){
// loop through CSV data
dataSet.forEach(function(data){
// if they match
if(geom.properties.WMA_DWAF_I === +data.id){
// loop through all years
for(var datum in data){
// if isn't id code
if (datum != "id") {
// add CSV data to geom properties
geom.properties[datum] = +data[datum]; // convert from string to number
// push value to our array
dataValues.push(+data[datum]);
}
}
}
})
});
// determine cluster arrays from data values
var clusters = ss.ckmeans(dataValues, 5);
var breaks = clusters.map(function(cluster){
// return the last element of the cluster array
return cluster.pop();
});
// remove last array item for colorize domain
breaks.splice(-1,1);
// update colorize function with domain values
colorize.domain(breaks);
// send updated geoms to be drawn
drawMap(geoms);
}
function drawMap(geoms) {
// append a g to the svg, use data from geoms
// and path generator to draw map
svg.append("g")
.selectAll("path")
.data(geoms.features)
.enter()
.append("path")
.attr("d", path)
.attr("class", "region");
// call to color map with initial/min value
updateMap(d3.select("#sequence").attr("min"));
}
function updateMap(year) {
// select all the regions
d3.selectAll('.region')
.attr("fill", function(d){
if(d.properties[year] != undefined) {
return colorize(d.properties[year]);
} else {
// something wrong with data
return 'lightgray'
}
});
}
// IIFE to attach listeners to range UI
(function() {
// select the output
var output = d3.select("#output");
// select range
d3.select('#sequence')
.on('input', function(d) { // when it changes
updateMap(+this.value); // update the map
output.html(+this.value) // update the output
});
})();
})();
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://unpkg.com/simple-statistics@4.1.0/dist/simple-statistics.min.js