javascript - How can I nest GeoJSON / TopoJSON geometries OR nest the generated paths with D3? -


problem:

i'm attempting create interactive map of in state, county , national boundaries displayed. counties shaded based on data, , hovering on state should highlight counties in state, , state should clickable. want achieve having svg county shapes inside of state shapes, inside of shape.

i can generate county map based on census county shape file, , can shade states based on data in external csv prepping file topojson command line , using following code in 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>

this visually acceptable (except doesn't have discrete state / national boundaries) - functionally inadequate. in order apply css counties on state hover, counties need within state shape, or grouped somehow.

what i've tried:

  • using topojson-merge in command line merge counties state shapes, , render state shapes separately - helps having discrete state borders - haven't figured way nest counties respective state shapes.

what i'm working out now:

  • somehow combining state topojson file , county topojson file , nesting counties in states, rendering d3.

  • somehow using d3 take non-nested state , county data , nest on client on client level.

in end learn effective , quickest rendering process achieve desired functionality.

thanks in advance.

i took punt on data sources, , here looks you're trying achieve: http://bl.ocks.org/benlyall/55bc9474e6d531a1c1fe

basically, have generated topojson file using following command line:

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 

some explanation on this:

  • -o counties_pa.json sets name of output file
  • --id-property=+geoid use property in input file id of each output geometry
  • -p means include properties input file
  • -e pop01.txt pull external data in file pop01.txt. file csv file generated pop01.xls spreadsheet available http://www.census.gov/support/usacdatadownloads.html#pop
  • --id-property=+stcou means id property external file (pop01.txt) in stcou column. used match matching ids in input file (which in geoid property explained above)
  • -p population=+pop010210d,area=aland,state=+statefp,county=+countyfp explicitly lists properties want in output file, won't included. pop010210d column name population @ 2010 census, used demonstration purposes.
  • cb_2014_us_county_20m.shp cb_2014_us_state_20m.shp 2 input files. 1 county shapes , 1 state shapes. each added output file in seperate properties named after filenames.

i did way, seemed colouring county areas based on population density, both population , area needed in output file. population pulled pop01 spreadsheet , linked each county based on geoid (which state number concatentated county number).

i looking quick , easy way recreate dataset, , add state boundaries post answer. not sure how closely matches original data, seems work demonstration purposes.

from that, took code above , updated to:

<!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> 

the new , interesting bits of code are:

  1. add data-state attribute each county determine state belongs to:

    .attr("data-state", function(d) { return d.properties.state; }) 
  2. add state boundaries (i combined states topojson file in topojson command line)

    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. added hover handlers can see how i'm determining grouping of counties states:

    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. tied these hover handlers each county executed @ appropriate times:

    .on("mouseover", hovercounty) .on("mouseout", outcounty); 

Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -