问题描述
有没有办法用 D3.js 将某些县组合在一起?
我正在显示美国的县级地图,我想在县组周围绘制边界或突出显示县组。
我有一个每个县的数组(通过 d.id
在绘制县时分配),但我不确定如何定位该属性或在一组元素周围绘制边框那些属性。
<script>
var svg = d3.select("svg");
var path = d3.geoPath();
d3.json("https://d3js.org/us-10m.v1.json",function(error,us) {
if (error) throw error;
// draw counties
svg.append("g")
.attr("class","counties")
.selectAll("path")
.data(topojson.feature(us,us.objects.counties).features)
.enter().append("path")
.attr("d",path)
.on("click",clicked)
svg.append("path")
.attr("class","county-borders")
.attr("d",path(topojson.mesh(us,us.objects.counties,function(a,b) { return a !== b; })));
// draw states
svg.append("g")
.attr("class","states")
.selectAll("path")
.data(topojson.feature(us,us.objects.states).features)
.enter().append("path")
.attr("d",path);
svg.append("path")
.attr("class","state-borders")
.attr("d",us.objects.states,b) { return a !== b; })));
function clicked(d) {
console.log(d.id);
}
var example_group = [45001,45003,45005,45007,45009,45011];
});
</script>
解决方法
topojson 库具有合并方法。由于您使用的是 topojson,因此合并功能非常简单。 但是,如果您计划进行多次合并并具有静态分组,则创建合并数据以提供服务(而不是每次加载时在浏览器中合并)可能是首选,这可能只涉及保存由下面的 topojson.merge 创建的 geojson。
首先,我们使用特征 ID 进行一些分组:
// groups:
var groups = [
[45001,45003,45005,45007,45009,45011],[32023,32003,06027,32017,49053,4015]
];
然后我们为每一个运行 topojson.merge:
var groupedCounties = groups.map(function(group) {
return topojson.merge(us,us.objects.counties.geometries.filter(function(d) {
return group.indexOf(+d.id) > -1; // Merge criteria.
}))
})
这将返回一组 geojson 特征,因此我们可以直接将其与 d3.geoPath 一起使用。
现在我们只画它们:
svg.selectAll(null)
.data(groupedCounties)
.enter()
.append("path")
.attr("d",path)
....
如下图所示:
var svg = d3.select("svg");
var path = d3.geoPath();
d3.json("https://d3js.org/us-10m.v1.json",function(error,us) {
if (error) throw error;
// for fitting in snippet view (somewhat)
path.projection(d3.geoIdentity().fitSize([500,300],topojson.feature(us,us.objects.counties)))
svg.append("path")
.attr("class","county-borders")
.attr("d",path(topojson.mesh(us,us.objects.counties,function(a,b) { return a !== b; })));
// draw states
svg.append("g")
.attr("class","states")
.selectAll("path")
.data(topojson.feature(us,us.objects.states).features)
.enter().append("path")
.attr("d",path);
// groups:
var example_group = [45001,45011];
var example_group2 = [32023,4015];
// make an array of groups:
var groups = [example_group,example_group2];
// make features out of these:
var groupedCounties = groups.map(function(group) {
return topojson.merge(us,us.objects.counties.geometries.filter(function(d) { return group.indexOf(+d.id) > -1; }))
})
console.log(groupedCounties);
// draw grouped features:
svg.selectAll(null)
.data(groupedCounties)
.enter()
.append("path")
.attr("d",path)
.style("fill",function(d,i) {
return ["orange","steelblue"][i];
})
});
.states{
fill: none;
stroke: black;
stroke-width: 1px;
}
.county-borders {
fill:none;
stroke: #ccc;
stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<svg width="500" height="300"></svg>