如何嵌套GeoJSON/TopoJSON几何图形或使用D3嵌套生成的路径? [英] How can I nest GeoJSON / TopoJSON geometries OR nest the generated paths with 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
设置输出文件的名称 -
--id-property=+GEOID
将在输入文件中使用该属性作为每个输出几何的id
-
-p
表示包括输入文件中的所有属性 -
-e POP01.txt
将从文件POP01.txt
中提取外部数据.此文件是从POP01.xls
电子表格生成的csv文件,可从 http://www获得. census.gov/support/USACdataDownloads.html#POP -
--id-property=+STCOU
表示外部文件(POP01.txt
)的id属性在STCOU列中.用来与输入文件中的匹配id
匹配(如上所述,该属性位于GEOID
属性中) -
-p population=+POP010210D,area=ALAND,state=+STATEFP,county=+COUNTYFP
在输出文件中显式列出我想要的属性,因此不会包含任何其他内容. POP010210D是2010年人口普查人口总数的栏目名称,因此我仅将其用作演示目的. -
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 theid
of each output geometry-p
means include all properties from the input file-e POP01.txt
will pull external data in from the filePOP01.txt
. This file is a csv file generated from thePOP01.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 matchingid
s in the input file (which are in theGEOID
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>
有趣的新代码是:
-
为每个县添加
data-state
属性,以确定其属于哪个州:
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屋!