2016-06-04 5 views
4

Мне нужно создать в D3 диаграмму, как это: enter image description hereИнтерактивный график Европы с помощью D3

Карта Европы (здесь очень упрощается с использованием квадратики вместо стран), чьи страны окрашены в соответствии с количеством смертей (вызванных болезнью выбора), которые были отобраны в этом году.

Больше цвета темнее и тем больше смертей (как описано в легенде).

Пользователь может выбрать год, который предпочитает использовать слайдер, и может выбрать болезнь с помощью переключателя. В зависимости от года и выбранной болезни, изменение цвета в странах.

Когда пользователь убирает курсор мыши на той или иной стране (например, Франция), справа появляется некоторые детали, как:

  • страны
  • год
  • число от общего числа смертей
  • число смертей, деленное на мужчин и женщин

Мой набор данных делается следующим образом:

"","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 
... 

Я искал, если есть какая-либо схожая графика, которую я могу использовать, но ничего не нашел.

Я попытался создать карту Европы, и это то, что я получил https://plnkr.co/edit/Ny0lUkVoiKeP76R95eVn?p=preview.

Диаграмма не работает, так как ей не хватает файла europe.json. Plunker не сохраняет, потому что файл слишком велик. Это является europe.json файлы и это то, что я вижу (если я прохожу курсор Франция): enter image description here

В script.js файл представляет собой фрагмент кода (комментировал), который не работает. Это первый раз, когда я делаю графику с картами.

Хорошо, теперь я не знаю с чего начать. Как я могу, например, связать название страны с выбранной страной? И фильтровать данные в базовом году и болезни? Может ли кто-нибудь дать мне руку?

Я знаю, что я много прошу, но мне не нужен весь код, но помощь, чтобы двигаться вперед, чтобы развить график.

спасибо


Я почти закончил диаграмму, есть только две вещи, которые я не могу исправить: легенда и цвет тех стран, которые не меняются с выбранного года.

Вот код: PLUNKER

Для легенды я использовал library of Susie Lu. Легенда создана, но не окрашена. Я попытался изменить диапазон и использовать то же, что я использовал для окраски стран, но не работает.

// 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); 

Вторая проблема заключается в том, что если пользователь меняет год с помощью ползунка, цвет стран не изменяется. Я не понимаю, как обновить значение ползунка. Справа данные берутся правильно.

Не мог бы кто-нибудь мне помочь?

PS: Я не знаю, был ли я прав, чтобы изменить этот вопрос или мне пришлось открыть другой. В любом случае, спасибо.

+1

Прежде всего: не используйте json, а используйте .topojson. Это карта .json ориентирована на веб-сайт и имеет 10% от размера. Используйте эту страницу для перевода с json на topojson: http://geojson.io загрузите файл и сохраните его как TopoJSON – Klaujesi

+0

В вашем наборе данных есть неправильное определение заголовка, присвойте любое имя первому столбцу, то есть: id. «id», «Country», «Year», «Sex», «Death», «Value» – Klaujesi

+0

, пожалуйста, присоединитесь к этой комнате: http://chat.stackoverflow.com/rooms/113858/interactive-map – Klaujesi

ответ

2

Это не полное решение для вашего ответа, но дает вам общий шаблон, который я использую.

  • Установить начальные значения, подготовить сценарий для интерфейса
  • вызова для передачи данных на сервер и ждать его появления
  • Рисовать карту базы, добавить слушатель событий для взаимодействия с пользователем
  • Фильтра и выберите apropiate информация в зависимости от действий пользователя

Установить начальные значения, подготовить сценарий для интерфейса

нагрузки скрипты

<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); 

Нужно прочитать: Let’s Make a Map

вызова данных на сервер и ждать, пока она прибудет Вы должны подождать, пока все данные или пользователь могут начать взаимодействовать с некоторыми из них и получить ошибки, неопределенные значения и т. Д.

Рекомендация: отделите базу данных от своих данных. Вы можете изменять карту и/или данные без повторного создания всего вашего json снова и снова. Легко

означает сохранение
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 

должна прочитать: Queue

Draw карта базу, добавить прослушиватель событий для взаимодействия с пользователем Draw карты.Добавить прослушиватель событий на "при наведении курсора мыши" и "отведении указателя мыши":

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

Инструменты: TopoJSON Maps - Letfleat map tool

Фильтр и выберите apropiate информацию в зависимости от действий пользователя У вас есть взаимодействие двух типов:

  • пользователя по стране (функция ShowInfo)
  • пользователь выбирает desseas или год (функция обновления)

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() это один из самых мощных функции D3 для обработки данных и подмножества данных.

должен прочитать: Groupin Data - Arrays API - D3 using nest on csv data - Reading in Data

Инструменты: Mister Nester

PS:

Я изменил свой .csv, добавив столбец связывать .topojson код страны до .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 

каждая страна имеет код (indx), поэтому, когда вы выбираете страну, пройдите код для фильтрации данных из csv.

+0

Я понимаю (не все), как это работает, и я пытаюсь изменить код в соответствии с моими потребностями. Я пытаюсь показать текст (содержащийся в div '# info'), взятый из csv, только когда мышь проходит над страной. Если мышь отсутствует в стране, мне бы хотелось, чтобы текст не отображался. Как я могу это сделать? Я попытался создать логическое значение false, которое становится истинным внутри метода showInfo'. Но это не работает. Я пару часов пробовал, но не могу найти решение. Не могли бы вы помочь (снова)? – four

+1

Просто добавьте: $ ("# info"). Html ("") при выводе мыши: .on ("mouseout", function (d) { d3.select ("# coun" + d.properties.indx) .style ('stroke', 'ddd'). style ("stroke-width", 1) $ ("# info"). html ("") }) – Klaujesi

+0

Эй, я обновляю свое главное сообщение некоторыми " маленькая "проблема. Вы можете мне помочь? Большое спасибо – four

Смежные вопросы