I need to create in D3 a chart like this:
A map of Europe (here is very simplified using squares instead of countries) whose countries are colored according to the
This is not a complete solution to your answer, but gives you a general pattern I use.
Set initial values, prepare the scenario for interface
Load scripts
D3 base
TopoJSON
Queue
jQuery
HTML
JavaScript
// width and height
var w = 800, h = 600, dess;
// define map projection
var projection = d3.geo.mercator()
.center([13, 52])
.translate([w/2, h/2])
.scale([w/1.5]);
// define path generator
var path = d3.geo.path()
.projection(projection);
// create SVG
var svg = d3.select("#container")
.append("svg")
.attr("width", w)
.attr("height", h);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
Must-read: Let’s Make a Map
Call for data to server and wait for it arrives You must wait for all data or user could start interact with some of them and get error, undefined values and so on.
Recomendation: separate your Map base from your data. You can change map and/or data without recreate all your json over and over again. Easy to mantain
d3_queue.queue()
.defer(d3.json, 'data/europe.topojson') //<-- Topojson base map
.defer(d3.csv, 'data/dessease.csv') //<-- dessease csv data
.awaitAll(makemap); // <-- When data arrives call makemap function
Must-Read: Queue
Draw map base, add event listener to interact with the user Draw map. Add event listener on "mouseover" and "mouseout":
function makemap(error, europe, dessease) {
dess = dessease.slice()
counties = topojson.feature(europe, europe.objects.collection);
vector = svg.selectAll("path")
.data(counties.features)
.enter()
.append("path")
.attr("class", "county")
.attr("id", function(d){
return "coun"+d.properties.indx})
.attr("d", path)
.on("mouseover", function(d) {
d3.select("#coun"+d.properties.indx).style('stroke', '777').style("stroke-width",2)
showInfo(d)
})
.on("mouseout", function(d) {
d3.select("#coun"+d.properties.indx).style('stroke', 'ffffd').style("stroke-width",1)
$("#info").html("")
})
};
Must-Read: TopoJSON
Tools: TopoJSON Maps - Letfleat map tool
Filter and select the apropiate info depending on user action You have two type interaction:
Javascript
var showInfo = function (d) { // Populate the tooltip
var infoNest = d3.nest()
.key(function(d) { return d.Year }) //<-- Filter selectors
.key(function(d) { return d.Sex; }) // Now you use
.map(dess); //<-- your csv data
$("#info").html($("#rango").val() + " - "+d.properties.name+" : "+JSON.stringify(infoNest['1998']['Male']) ) // sample
}
var update = function () { // change map color based on values
var des = $('input[name=desse]:checked', '#desses').val();
$("#info").html($("#rango").val()+ " : " + des)
}
$('#desses').on('change', update);
$("#rango").on("input", update);
d3.nest() it's one of the most powerfull function of D3 to deal with data and subset of data.
Must-Read: Groupin Data - Arrays API - D3 using nest on csv data - Reading in Data
Tools: Mister Nester
PS:
I've changed your .csv adding a column to bind .topojson country code to .csv:
indx,id,Country,Year,Sex,Death,Value
4,3,Austria,2012,Male,Tuberculosis,18
4,4,Austria,2012,Male,Tetanus,1
4,5,Austria,2012,Male,Diphtheria,0
4,1641,Austria,2012,Female,Tuberculosis,7
4,1642,Austria,2012,Female,Tetanus,0
4,1643,Austria,2012,Female,Diphtheria,0
4,3409,Austria,2011,Male,Tuberculosis,27
4,3410,Austria,2011,Male,Tetanus,0
4,3411,Austria,2011,Male,Diphtheria,0
4,5047,Austria,2011,Female,Tuberculosis,14
4,5048,Austria,2011,Female,Tetanus,0
4,5049,Austria,2011,Female,Diphtheria,0
4,46829,Austria,1998,Male,Tuberculosis,61
4,46830,Austria,1998,Male,Tetanus,0
4,46831,Austria,1998,Male,Diphtheria,0
4,48341,Austria,1998,Female,Tuberculosis,30
4,48342,Austria,1998,Female,Tetanus,0
4,48343,Austria,1998,Female,Diphtheria,0
2,59309,Belgium,2010,Male,Tuberculosis,13
2,59310,Belgium,2010,Male,Tetanus,0
2,59311,Belgium,2010,Male,Diphtheria,0
2,60947,Belgium,2010,Female,Tuberculosis,13
2,60948,Belgium,2010,Female,Tetanus,2
2,60949,Belgium,2010,Female,Diphtheria,0
each country has a code (indx), so when you select a country pass the code to filter data from csv.