Interactive graph of Europe using D3

后端 未结 1 1475
执笔经年
执笔经年 2020-12-20 04:37

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

1条回答
  •  -上瘾入骨i
    2020-12-20 04:47

    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
    • Call for data to server and wait for it arrives
    • Draw map base, add event listener to interact with the user
    • Filter and select the apropiate info depending on user action

    Set initial values, prepare the scenario for interface

    Load scripts

              D3 base
                 TopoJSON
                 Queue
                jQuery
    

    HTML

    Tuberculosis
    Tetanus
    Diphtheria

    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:

    • user over a country (showInfo function)
    • user select desseas or year (update function)

    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.

    0 讨论(0)
提交回复
热议问题