欧洲使用D3的互动图 [英] Interactive graph of Europe using D3

查看:145
本文介绍了欧洲使用D3的互动图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在D3中创建如下图表:



欧洲地图这里是非常简化使用正方形而不是国家),其国家根据在一年中选择的死亡数量(由选择疾病引起)着色。



更多的颜色是黑暗的,死亡人数越多(如图例中所述)。



用户可以选择使用滑块的年份,并可选择疾病使用单选按钮。
根据年份和选择的疾病,国家的颜色变化。



当用户将鼠标移动到特定国家(例如法国)右侧会显示一些详细信息:




  • 国家


  • 总死亡人数

  • 死亡人数除以男性和女性



我的数据集是这样完成的:

 ,国家,年,性别 ,价值
3,奥地利,2012,男性,结核病,18
4,奥地利,2012 Tetanus,1
5,Austria,2012,Male,Diphtheria,0
1641,Austria,2012 Tuberculosis,7
1642,Austria,2012,Female,Tetanus,0
1643,Austria,2012 Diphtheria,0
3409,Austria,2011,Male,Tuberculosis,27
3410,Austria,2011 Tetanus,0
3411,Austria,2011,Male,Diphtheria,0
5047,Austria,2011 Tuberculosis,14
5048,Austria,2011,Female,Tetanus,0
5049,Austria,2011 白喉,0
46829,奥地利,1998,男性,结核病,61
46830,奥地利,1998 Tetanus,0
46831,Austria,1998,Male,Diphtheria,0
48341,Austria,1998 结核病,30
48342,奥地利,1998,女性,破伤风,0
48343,奥地利,1998 Diphtheria,0
59309,Belgium,2010,Male,Tuberculosis,13
59310,Belgium,2010 Tetanus,0
59311,Belgium,2010,Male,Diphtheria,0
60947,Belgium,2010 结核病,13
60948,比利时,2010,女性,破伤风,2
60949,比利时,2010 Diphtheria,0
...

我搜索过,如果有任何类似的图形我可以使用,但我什么也找不到。



我试图创建欧洲地图,这是我得到的



在script.js文件是一段代码(注释),不工作。
这是我第一次使用地图制作图形。



确定现在我不知道从哪里开始。
例如,如何根据所选国家/地区关联国家/地区的名称?
并筛选基年和疾病的数据?
有人可以给我一只手吗?



我知道我在问很多,但我不想要所有的代码,但是有一个帮助,以便能够向前开发图。



感谢这么多






我差不多完成了图表,我不能解决的两件事情:国家的传说和颜色,在选定年份不变。



这里的代码: PLUNKER



对于图例,我使用了 Susie Lu 图书馆。
图例已创建但未着色。我尝试更改范围,并使用相同的颜色国家,但不工作。

  //颜色国家
var colors = d3.scale.linear()
.domain([0,1,2300])
.range([#cccccc,#131313,# ba3c28]);
/ **
*图例。
* /
var quantize = d3.scale.quantize()
.domain([0,1,2300])
//.range([#cccccc #131313,#ba3c28]);
.range(d3.range(10).map(function(i){
returnq+ i +-10;
}))

var svg = d3.select(#leftDown)
.append(svg)
.attr(class,legendQuantsvg);

svg.append(g)
.attr(class,legendQuant)
.attr(transform,translate(20,20) );

var legend = d3.legend.color()
.labelFormat(d3.format(。0f))
.useClass(true)
.scale (量化)。

svg.select(。legendQuant)
.call(legend);

第二个问题是,如果用户使用滑块更改年份,国家的颜色不变。
我不明白如何更新滑块的值。
在右边数据正确。



有人可以帮我吗?



我不知道我是否是正确的改变这个问题,或者如果我不得不打开另一个。
无论如何,谢谢。

解决方案

这不是一个完整的解决方案,




  • 设置初始值,为接口准备场景

  • 调用服务器的数据,

  • 绘制地图基础,添加事件监听器以与用户互动

  • 根据用户操作过滤并选择相应信息



设置初始值,为接口准备方案



载入脚本

 < script src =js / d3.jscharset =utf-8> ; / script> D3 base 
< script src =js / topojson.v1.min.js>< / script> TopoJSON
< script src =js / d3-queue.v2.min.js>< / script> Queue
< script src =js / jquery-2.2.4.min.js>< / script> jQuery

HTML

 < div id =selector> 
< form id =desses>
< input type =radioname =dessevalue =tuberculosischecked> Tuberculosis< br>
< input type =radioname =dessevalue =tetanus>破伤风< br>
< input type =radioname =dessevalue =diphtheria> Diphtheria
< / form>
< / div>
< input type =rangeid =rangovalue =2014min = 2004 max = 2014>
< div id =container>< / div>
< div id =info>< / div>

JavaScript

  // width and height 
var w = 800,h = 600,dess;

//定义映射投影
var projection = d3.geo.mercator()
.center([13,52])
.translate 2,h / 2])
.scale([w / 1.5]);

//定义路径生成器
var path = d3.geo.path()
.projection(projection);

//创建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 ,0);

必须阅读:让我们制作地图



向服务器调用数据并等待到达
您必须等待所有数据或用户可以开始与其中一些交互,并得到错误,未定义的值等。



建议:将您的地图基础您的数据。您可以更改地图和/或数据,而不重新创建所有的json一遍又一遍。容易找到

  d3_queue.queue()
.defer(d3.json,'data / europe.topojson' )//< - Topojson base map
.defer(d3.csv,'data / dessease.csv')//< - dessease csv data
.awaitAll(makemap); //< - 当数据到达时调用makemap函数

必须读取:队列



绘制地图基础,添加事件监听器与用户交互
绘制地图。在mouseover和mouseout上添加事件监听器


$ b

  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){
returncoun+ d.properties.indx})
.attr ,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','ddd')。style(stroke-width,1)
$(#info)。html b $ b})
};

必须阅读: TopoJSON



工具: TopoJSON地图 - Letfleat地图工具



根据用户操作过滤并选择相应的信息
您有两种类型的交互:




  • 用户在某个国家/地区(showInfo功能)

  • 用户选择desseas或年份(更新功能)



JavaScript

  var showInfo = function(d){//填充工具提示
var infoNest = d3.nest()
.key(function(d){return d.Year})//< - 过滤器选择器
.key(function(d){return d.Sex; })//现在你使用
.map(dess); //< - your csv data
$(#info)。html($(#rango)。val()+ - + d.properties.name +:+ JSON。 stringify(infoNest ['1998'] ['Male']))// sample
}
var update = function(){//根据值改变地图颜色
var des = $ ('input [name = desse]:checked','#desses')。val();
$(#info)。html($(#rango)。val()+:+ des)
}
$('#desses')。on ('change',update);
$(#rango)。on(input,update);

d3.nest()它是D3最强大的功能之一



必须读取: Groupin Data - Arrays API - D3在csv数据上使用嵌套 - 读取资料



工具: Nister先生



PS



ve更改了.csv添加列以将.topojson国家/地区代码绑定到.csv:

  indx,id,性别,死亡,价值
4,3,奥地利,2012,男性,结核病,18
4,4,奥地利,2012年,男性,破伤风,1
4,5,奥地利,2012 ,男性,白喉,0
4,1641,奥地利,2012,女性,结核病,7
4,1642,奥地利,2012,女性,破伤风,0
4,1643, 2012年,女性,白喉,0
4,3409,奥地利,2011,男性,结核病,27
4,3410,奥地利,2011,男性,破伤风,0
4,3411,奥地利,2011年,男性,白喉,0
4,5047,奥地利,2011,女性,结核病,14
4,5048,奥地利,2011,女性,破伤风,0
4,5049,奥地利,2011年,女性,白喉,0
4,46829,奥地利,1998年,男性,结核病,61
4,46830,奥地利,1998年,男性,破伤风,0
4,46831 ,奥地利,1998年,男性,白喉,0
4,48341,奥地利,1998年,女性,结核病30
4,48342,奥地利,1998年,女性,Tetanus,0
4, 48343,奥地利,1998年,女性,白喉,0
2,59309,比利时,2010年,男性,结核病,13
2,59310,比利时,2010年,男性,破伤风,0
2 ,59311,比利时,2010年,男性,白喉,0
2,60947,比利时,2010,女性,结核病,13
2,60948,比利时,2010,女性,破伤风,2
2,60949,比利时,2010,女,白喉,0

每个国家都有一个代码,因此当您选择国家/地区时,通过代码从csv过滤数据。


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 number of deaths (caused by the choice disease) that have been selected in the year.

More color is dark and the greater the number of deaths (as described in the legend).

The user can choose the year that prefers using a slider and can choose the disease using a radio button. According to the year and selected disease, the color change of the countries.

When the user rolls the mouse over a particular country (eg France), on the right appears some details like:

  • the country
  • year
  • the number of total deaths
  • the number of deaths divided by male and female

My dataset is done this way:

"","Country","Year","Sex","Death","Value"
"3","Austria","2012","Male","Tuberculosis",18
"4","Austria","2012","Male","Tetanus",1
"5","Austria","2012","Male","Diphtheria",0
"1641","Austria","2012","Female","Tuberculosis",7
"1642","Austria","2012","Female","Tetanus",0
"1643","Austria","2012","Female","Diphtheria",0
"3409","Austria","2011","Male","Tuberculosis",27
"3410","Austria","2011","Male","Tetanus",0
"3411","Austria","2011","Male","Diphtheria",0
"5047","Austria","2011","Female","Tuberculosis",14
"5048","Austria","2011","Female","Tetanus",0
"5049","Austria","2011","Female","Diphtheria",0
"46829","Austria","1998","Male","Tuberculosis",61
"46830","Austria","1998","Male","Tetanus",0
"46831","Austria","1998","Male","Diphtheria",0
"48341","Austria","1998","Female","Tuberculosis",30
"48342","Austria","1998","Female","Tetanus",0
"48343","Austria","1998","Female","Diphtheria",0
"59309","Belgium","2010","Male","Tuberculosis",13
"59310","Belgium","2010","Male","Tetanus",0
"59311","Belgium","2010","Male","Diphtheria",0
"60947","Belgium","2010","Female","Tuberculosis",13
"60948","Belgium","2010","Female","Tetanus",2
"60949","Belgium","2010","Female","Diphtheria",0
...

I searched if there were any similar graphics that I can use, but I found nothing.

I tried to create a map of Europe and this is what I got https://plnkr.co/edit/Ny0lUkVoiKeP76R95eVn?p=preview.

The chart does not work because it lacks the europe.json file. Plunker doesn't save becasue file is too large. This is the europe.json files and this is what I see (if I pass the mouse over France):

In script.js file is a piece of code (commented) that does not work. It is the first time I make graphics with maps.

Ok now I don't know where to begin. How can I for example to associate the name of the country based on the country selected? And to filter the data in the base year and the disease? Could someone give me a hand?

I know I'm asking a lot, but I don't want all the code but a help to be able to move forward to develop the graph.

Thanks so much


I almost finished the chart, there are only two things that I can't fix: the legend and the color of the countries that doesn't change with the selected year.

Here the code: PLUNKER

For the legend I used the library of Susie Lu. The legend is created but not colored. I tried to change the range and use the same I used to color the countries but doesn't work.

// to color countries
var colors = d3.scale.linear()
    .domain([0, 1, 2300]) 
    .range(["#cccccc","#131313", "#ba3c28"]);
/**
 * Legend.
 */
var quantize = d3.scale.quantize()
    .domain([0, 1, 2300])
    //.range(["#cccccc","#131313", "#ba3c28"]);
    .range(d3.range(10).map(function(i) { 
        return "q" + i + "-10"; 
    }));

var svg = d3.select("#leftDown")
    .append("svg")
    .attr("class", "legendQuantsvg");

svg.append("g")
    .attr("class", "legendQuant")
    .attr("transform", "translate(20, 20)");

var legend = d3.legend.color()
    .labelFormat(d3.format(".0f"))
    .useClass(true)
    .scale(quantize);

svg.select(".legendQuant")
    .call(legend);

The second problem is that if the user changes the year using the slider, the color of the countries does not change. I don't understand how to update the value of the slider. In the right the data are taken correctly.

Could someone help me?

PS: I don't know if I was right to change this question or if I had to open another. Anyway, thanks.

解决方案

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

    <script src="js/d3.js" charset="utf-8"></script>      D3 base
    <script src="js/topojson.v1.min.js"></script>         TopoJSON
    <script src="js/d3-queue.v2.min.js"></script>         Queue
    <script src="js/jquery-2.2.4.min.js"></script>        jQuery

HTML

<div id="selector">
<form id="desses">
  <input type="radio" name="desse" value="tuberculosis" checked>Tuberculosis<br>
  <input type="radio" name="desse" value="tetanus">Tetanus<br>
  <input type="radio" name="desse" value="diphtheria">Diphtheria
</form>
</div>
<input type="range" id="rango" value="2014" min=2004 max=2014>
<div id="container"></div>
<div id="info"></div>

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', 'ddd').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.

这篇关于欧洲使用D3的互动图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆