如何嵌套GeoJSON/TopoJSON几何图形或使用D3嵌套生成的路径? [英] How can I nest GeoJSON / TopoJSON geometries OR nest the generated paths with D3?

查看:100
本文介绍了如何嵌套GeoJSON/TopoJSON几何图形或使用D3嵌套生成的路径?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

我正在尝试创建一个显示州,县和国家边界的美国交互式地图.县基于数据着色,并且将鼠标悬停在一个州上应突出显示该州中的所有县,并且该州应是可单击的.我想通过将SVG的州县形状设置在州形状内,美国形状的内部来实现.

I'm attempting to create an interactive map of the US in which state, county and national boundaries are displayed. Counties are shaded based on data, and hovering over a state should highlight all counties in the state, and the state should be clickable. I want to achieve this by having a SVG with the county shapes inside of state shapes, inside of a US shape.

我可以基于CENSUS县形状文件生成县地图,并且可以通过使用TopoJSON命令行在文件中准备文件并在D3中使用以下代码来基于外部CSV中的数据对州进行着色:

I can generate a county map based on a CENSUS county shape file, and I can shade the states based on data in an external CSV by prepping the file with TopoJSON command line and using the 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>

这在视觉上几乎是可以接受的(除非它没有离散的州/国家/地区边界)-但在功能上不足够.为了将CSS应用于状态悬停的县,县需要处于州形状内或以某种方式进行分组.

This is mostly visually acceptable (except it doesn't have discrete state / national boundaries) - but is functionally inadequate. In order to apply CSS to the counties on a state hover, the counties need to be within a state shape, or grouped somehow.

我尝试过的事情:

  • 在命令行中使用topojson-merge将县合并为州形状,然后分别渲染州形状-这有助于使用离散的州边界-但我还没有找到将县嵌套在各自州中的方法状态形状.

我现在正在做什么:

  • 以某种方式将状态TopoJSON文件和县级TopoJSON文件组合在一起,并将县嵌套在州中,然后使用D3进行渲染.

  • Somehow combining a state TopoJSON file and a county TopoJSON file and nesting the counties in the states, then rendering with D3.

以某种方式使用d3来获取非嵌套的州和县数据,并将其嵌套在客户端的客户端级别上.

Somehow using d3 to take non-nested state and county data and just nest it on the client on the client level.

最后,我想学习最有效,最快的渲染过程,以实现所需的功能.

In the end I would like to learn about the most effective and quickest rendering process to achieve my desired functionality.

非常感谢您的帮助.

推荐答案

我在您的数据源上碰了碰,这就是您想要实现的效果:

I took a punt on your data sources, and here is what it looks like you're trying to achieve: http://bl.ocks.org/benlyall/55bc9474e6d531a1c1fe

基本上,我已经使用以下命令行生成了TopoJSON文件:

Basically, I have generated a TopoJSON file using the 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

对此有一些解释:

  • -o counties_pa.json sets the name of the output file
  • --id-property=+GEOID will use that property in the input file as the id of each output geometry
  • -p means include all properties from the input file
  • -e POP01.txt will pull external data in from the file POP01.txt. This file is a csv file generated from the POP01.xls spreadsheet available from http://www.census.gov/support/USACdataDownloads.html#POP
  • --id-property=+STCOU means that the id property from the external file (POP01.txt) is in the STCOU column. This is used to match up with matching ids in the input file (which are in the GEOID property as explained above)
  • -p population=+POP010210D,area=ALAND,state=+STATEFP,county=+COUNTYFP explicitly lists the properties that I want in the output file, so anything extra won't be included. POP010210D is the column name for the population as at the 2010 census, so I just used that for demonstration purposes.
  • cb_2014_us_county_20m.shp cb_2014_us_state_20m.shp are the two input files. One for county shapes and one for state shapes. They will each be added to the output file in seperate properties named after their filenames.

我这样做是因为您似乎正在根据人口密度为县区着色,因此人口和面积都需要包含在输出文件中.人口是从POP01电子表格中提取的,并根据GEOID(只是与县号对应的州号)链接到每个县.

I did it this way, as you seemed to be colouring your county areas based on population density, so both population and area needed to be in the output file. The population was pulled from the POP01 spreadsheet and linked to each county based on the GEOID (which is just the state number concatentated with the county number).

我只是在寻找一种快速简便的方法来重新创建您的数据集,然后向其添加状态边界,以便发布答案.不确定这与原始数据的匹配程度如何,但它似乎可以用于演示.

I was just looking for a quick and easy way to recreate your dataset, and then add the state boundaries to it so I could post the answer. Not sure how closely this matches your original data, but it seems to work for demonstration purposes.

从那开始,我将您的代码放在上面,并将其更新为:

From that, I took your code above and updated it 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>

有趣的新代码是:

  1. 为每个县添加data-state属性,以确定其属于哪个州:

  1. Add a data-state attribute to each county to determine which state it belongs to:

.attr("data-state", function(d) { return d.properties.state; })

  • 添加状态边界(我将状态组合到topojson命令行中的TopoJSON文件中)

  • Add the state boundaries (I combined states to the TopoJSON file in the 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);
    });
    

  • 添加了悬停处理程序,因此您可以看到我如何确定将县分组为州:

  • Added hover handlers so you can see how I'm determining the grouping of counties into 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);
    }
    

  • 将这些悬停处理程序绑定到每个县,以便它们在适当的时间被执行:

  • Tied these hover handlers to each county so they get executed at the appropriate times:

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

  • 这篇关于如何嵌套GeoJSON/TopoJSON几何图形或使用D3嵌套生成的路径?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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