2015-06-14 5 views
0

Проблема:Как я могу вложить геометрию GeoJSON/TopoJSON ИЛИ вложить сгенерированные пути с помощью D3?

Я пытаюсь создать интерактивную карту США, в которой отображаются государственные, уездные и национальные границы. Границы затенены на основе данных, а зависание над состоянием должно выделять все округа в состоянии, а состояние должно быть кликабельным. Я хочу достичь этого, имея SVG с формами графства внутри форм штата, внутри формы США.

я могу генерировать графство карты на основе файл формы CENSUS округа, и я могу тень государство, основанное на данных во внешнем CSV по готовя файл с командной строкой TopoJSON и используя следующий код в D3:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 

 
path { 
 
    fill: none; 
 
    stroke-linejoin: round; 
 
    stroke-linecap: round; 
 
} 
 

 
</style> 
 
<body> 
 
<script src="http://d3js.org/d3.v3.min.js"></script> 
 
<script src="http://d3js.org/topojson.v1.min.js"></script> 
 
<script> 
 

 
var width = 960, 
 
    height = 600; 
 

 
var path = d3.geo.path() 
 
    .projection(d3.geo.albersUsa()); 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width) 
 
    .attr("height", height); 
 

 
d3.json("counties_pa.json", function(error, us) { 
 
    if (error) return console.error(error); 
 

 
var color = d3.scale.threshold() 
 
    .domain([1, 10, 50, 100, 500, 1000, 2000, 5000]) 
 
    .range(["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"]); 
 

 

 

 
svg.append('g').attr('class','counties').selectAll("path").data(topojson.feature(us, us.objects.cb_2014_us_county_20m).features).enter().append('path').attr('d',path).attr('style',function(d){return 'fill:'+color(d.properties.population/d.properties.area * 2.58999e6);}); 
 

 
}); 
 

 

 

 
</script>

Это главным образом визуально приемлемым (за исключением того, что не имеет дискретные государственные/национальные границы) - но функционально неадекватным. Чтобы применить CSS к округам при зависании состояния, уезд должен быть в форме государства или каким-то образом сгруппирован.

Что я пробовал:

  • Использование topojson-слияние в командной строке, чтобы объединить графства в государственные формы, а затем сделать государственные формы отдельно - это помогает с наличием отдельных государственных границ - но я не придумали способ вложить графства в соответствующие формы состояния.

Что я работаю прямо сейчас:

  • Каким-то образом комбинируя файл состояния TopoJSON и файл округа TopoJSON и гнездования округов в штатах, то рендеринг с D3.

  • Как-то используя d3, чтобы принимать не вложенные данные состояния и графства и просто вложить его на клиентском компьютере на уровне клиента.

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

Спасибо за вашу помощь заранее.

+0

Возможно, мне что-то не хватает, но вы можете просто взять данные о графствах, а для исходного цвета - все графства в состоянии (и их границах) одного цвета? –

+0

Возможно, вы могли бы использовать свойства в вашем файле topojson для сопоставления округов с состояниями, к которым они принадлежат. то есть. имеют свойство 'state' в каждом графстве, которое идентифицировало состояние, в котором они были, это позволит вам выбрать все соответствующие округа при зависании состояния. Я не совсем понимаю, чего вы пытаетесь достичь, кроме того, что выделяют округа при наведении штата. Если это так, то то, что я предложил, должно быть выполнимым. Где вы находите свои шейп-файлы округа, и имеет ли он состояние, в котором каждый округ принадлежит существующему имуществу, которое можно повторно использовать? –

ответ

2

Я взял плоскодонки на ваших источников данных, и вот что она выглядит, как вы пытаетесь достичь: http://bl.ocks.org/benlyall/55bc9474e6d531a1c1fe

В принципе, я сгенерировал файл TopoJSON, используя следующую командную строку:

topojson -o counties_pa.json --id-property=+GEOID -p -e POP01.txt --id-property=+STCOU -p population=+POP010210D,area=ALAND,state=+STATEFP,county=+COUNTYFP cb_2014_us_county_20m.shp cb_2014_us_state_20m.shp 

Некоторые пояснения по этому вопросу:

  • -o counties_pa.json задает имя выходного файла
  • --id-property=+GEOID будет использовать это свойство во входном файле в качестве id каждой геометрии выходного
  • -p средства включают в себя все свойства из входного файла
  • -e POP01.txt будет тянуть внешние данные в файл из POP01.txt. Этот файл представляет собой файл csv, сгенерированный из таблицы POP01.xls, доступный с http://www.census.gov/support/USACdataDownloads.html#POP.
  • --id-property=+STCOU означает, что свойство id из внешнего файла (POP01.txt) находится в столбце STCOU. Это используется для сопоставления с совпадением id s во входном файле (которые находятся в свойстве GEOID, как объяснялось выше)
  • -p population=+POP010210D,area=ALAND,state=+STATEFP,county=+COUNTYFP явно перечисляет свойства, которые я хочу в выходном файле, поэтому ничего лишнего не будет включено. POP010210D - это имя столбца для населения по состоянию на перепись 2010 года, поэтому я просто использовал это для демонстрационных целей.
  • cb_2014_us_county_20m.shp cb_2014_us_state_20m.shp - это два входных файла. Один для графских фигур и один для форм штата. Каждый из них будет добавлен в выходной файл в отдельных свойствах, названных по именам файлов.

Я сделал это таким образом, поскольку вы, казалось, раскрашивали свои округа, основываясь на плотности населения, поэтому как совокупность, так и область должны были быть в выходном файле. Население было вытащено из таблицы POP01 и привязано к каждому графству, основанному на GEOID (это всего лишь номер штата, совпадающий с номером графства).

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

От того, я взял свой код выше и обновлять его:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

path { 
    fill: none; 
    stroke-linejoin: round; 
    stroke-linecap: round; 
} 

path.state { 
    fill: none; 
    stroke: black; 
    stroke-width: .5px; 
} 

</style> 
<body> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script src="http://d3js.org/topojson.v1.min.js"></script> 
<script> 

var width = 960, 
    height = 600; 

var path = d3.geo.path() 
    .projection(d3.geo.albersUsa()); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

d3.json("counties_pa.json", function(error, us) { 
    if (error) return console.error(error); 

var color = d3.scale.threshold() 
    .domain([1, 10, 50, 100, 500, 1000, 2000, 5000]) 
    .range(["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"]); 

    svg.append('g') 
     .attr('class','counties') 
     .selectAll("path") 
     .data(topojson.feature(us, us.objects.cb_2014_us_county_20m).features).enter() 
     .append('path') 
     .attr('d', path) 
     .attr("id", function(d) { return "county-" + d.id; }) 
     .attr("data-state", function(d) { return d.properties.state; }) 
     .attr('style',function(d) { 
      return 'fill:'+color(d.properties.population/d.properties.area * 2.58999e6); 
     }) 
     .on("mouseover", hoverCounty) 
     .on("mouseout", outCounty); 

    svg.append('g') 
     .attr('class', 'states') 
     .selectAll("path") 
     .data(topojson.feature(us, us.objects.cb_2014_us_state_20m).features).enter() 
     .append("path") 
     .attr("class", "state") 
     .attr("id", function(d) { return "state-" + d.id; }) 
     .attr("d", path); 
    }); 

function hoverCounty(county) { 
    d3.selectAll("path[data-state='" + county.properties.state + "']").style("opacity", .5); 
} 

function outCounty(county) { 
    d3.select(".counties").selectAll("path").style("opacity", null); 
} 

</script> 

новых и интересных битов кода являются:

  1. Добавьте атрибут data-state для каждого округа, чтобы определить, какие что он принадлежит:

    .attr("data-state", function(d) { return d.properties.state; }) 
    
  2. Добавить государственную связанность s (я объединил состояние в файл TopoJSON в topojson командной строке)

    svg.append('g') 
        .attr('class', 'states') 
        .selectAll("path") 
        .data(topojson.feature(us, us.objects.cb_2014_us_state_20m).features).enter() 
        .append("path") 
        .attr("class", "state") 
        .attr("id", function(d) { return "state-" + d.id; }) 
        .attr("d", path); 
    }); 
    
  3. Добавлен обработчики при наведении курсора, так что вы можете увидеть, как я определить группировку округов в штаты:

    function hoverCounty(county) { 
        d3.selectAll("path[data-state='" + county.properties.state + "']").style("opacity", .5); 
    } 
    
    function outCounty(county) { 
        d3.select(".counties").selectAll("path").style("opacity", null); 
    } 
    
  4. Связал эти обработчик при наведении курсора мыши на каждое графство таким образом они получают, выполняемые в соответствующие моменты времени:

    .on("mouseover", hoverCounty) 
    .on("mouseout", outCounty); 
    
+0

Бен, это то, что я искал для вас большое спасибо. Я не знал, что вы можете использовать два шейп-файла в командной строке topojson. Также этот подход работает, но я задаюсь вопросом, может ли он быть менее подробным, буквально вставляя графства в состояниях так или иначе, и не нужно устанавливать каждый идентификатор округов (с состоянием) для использования в событии зависания. У меня есть хороший шанс переехать, и я очень ценю вашу помощь. –

+0

Не могли бы вы пойти по командной строке topojson, которую вы предоставили? Я немного отброшен, потому что я вижу значение -id-property (+ STCOU), которого нет в любом файле, и мне интересно, есть ли его тип или нет. Также я никогда не работал с двумя файлами и мог использовать более описательное понимание. –

+0

Я добавил объяснение в свой ответ, не стесняйтесь задавать любые дополнительные вопросы, если это необходимо. –

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

  • Нет связанных вопросов^_^