使用 D3.js 仅渲染 topojson 地图的一部分

Posted

技术标签:

【中文标题】使用 D3.js 仅渲染 topojson 地图的一部分【英文标题】:Rendering only a portion of a topojson map using D3.js 【发布时间】:2013-09-21 00:51:18 【问题描述】:

我正在使用 D3.js 库从美国人口普查 shapefile 创建地图。我正在寻找创建一个完整的美国地图,这没问题,每个州都有一张地图。

我的工作流程使用人口普查数据,由 ogr2ogr 在命令行根据需要进行更改,然后由 shpescape.com 转换为 topojson 或 geojson,由于 node.js 下载 topojson 模块时出错(见下文编辑的解决方案解决这个特殊问题)。

我的问题比其他任何问题都更像是一个实用问题——当使用此代码(以http://bl.ocks.org/mbostock/4707858 为模型)呈现时:

            var width = 640,
                height = 500;

            var projection = d3.geo.albers();

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

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

            d3.json("mt_geo.json", function(error, mt_topo) 
                var states = topojson.feature(mt_topo, mt_topo.objects.states),
                    state = states.features.filter(function(d)  return d.id === 34; )[0];
                projection
                    .scale(1)
                    .translate([0,0]);
                var b = path.bounds(state),
                    s = .95 / Math.max ((b[1][0]-b[0][0])/width, (b[1][1]-b[0][1])/height),
                    t = [(width-s*(b[1][0]+b[0][0]))/2, (height-s*(b[1][1]+b[0][1]))/2];
                projection
                    .scale(s)
                    .translate(t);
                svg.append("path")
                    .datum(states)
                    .attr("class", "feature")
                    .attr("d", path);
                svg.append("path")
                    .datum(topojson.mesh(us, us.objects.states,function(a, b) return a !== b;))
                    .attr("d", path);
                svg.append("path")
                    .datum(state)
                    .attr("class", "outline")
                    .attr("d", path);

它不仅在“var states”行抛出一个错误,上面写着“无法读取未定义的属性类型”——而且我也不知道我应该将什么传递给匿名函数,或者什么mt_topo.objects.states 应该参考。没有关于这种 GIS 的好文档。所有人口普查地图都有“州”特征吗?将 .shp 压缩为 topojson 时是否会丢失该信息?

简单地说,如果 d3.json 采用 (object, function(error, json)),那么实际工作的示例会是什么样子?

编辑: 解决方法和 WINDOWS 7 IDiosYNCRASIES -----

大多数教程告诉您使用 node.js 中的模块,但我在 Windows7 上,规范命令行“npm install -g topojson”在“上下文化”失败。创建者给我发了一个很好的link 来解决上述问题。

这很重要,因为在 topojson 的命令行中有一个标志,您可以在其中将 geojson 中的现有功能打包到 topojson 中的可访问对象中。例如,上面的代码在 topojson 中使用了“状态”——除非您使用以下命令,否则这是没有意义且无法访问的:

topojson -o us.topojson -- states=us_states.json

双连字符和状态之间的空格很重要。 然后,您可以通过 us.objects.states 访问状态,如上面的原始代码所示。

【问题讨论】:

你看过the tutorial吗?属性取决于数据中的内容,即完全由用户定义。 @LarsKotthoff -- 是的,我已经相当广泛地阅读了本教程。我想我发现了范围问题;就像你说的,它只是一个占位符。我原来的问题越来越清楚了。感谢您的帮助。 @kgilvi3:如果你找到了解决办法,请分享答案,我们很乐意 +1。 【参考方案1】:

你很亲密。在不测试您的代码的情况下,我看到了一个主要问题。您的 JSON 回调的第二个参数是 mt_topo,您在定义时使用

var states = topojson.feature(mt_topo, mt_topo.objects.states)

但是,稍后您使用 us 作为回调对象,大概是因为 Mike Bostock 在您引用的示例中使用了它。相反,应该是这样的:

svg.append("path")
 .datum(topojson.mesh(mt_topo, mt_topo.objects.states,function(a, b) return a !== b;))
 .attr("d", path);

也就是说,您的问题实际上是人口普查地图是否具有“州”功能。我的猜测是,您使用的任何几何图形都没有状态功能,这就是您遇到错误的原因。使用 topojson 命令行工具时,功能名称(即 data.objects.x)通常是输入文件的名称,因此如果您的文件是 US_Census_2010.shp,您需要将状态定义为

var states = topojson.feature(mt_topo, mt_topo.objects.US_Census_2010)

打开您的mt_geo.json 文件并查看您的功能的名称。希望对您有所帮助!

【讨论】:

因为我在这方面花了一些时间,所以我认为值得把它全部记录下来:@jczaplew,你绝对是正确的。我正在将最初在这里的内容添加到答案中作为解决方法。【参考方案2】:

表示地图的 GeoJSON 文件通常具有一个或多个特征。每个特征可能有零个或多个属性。通常,属性用于存储地点的元数据(州名、县等)。您可以阅读您的 GeoJSON 文件并查看它具有哪些属性,并使用此属性来显示或隐藏功能。

将文件从 GeoJSON 转换为 TopoJSON 时,you can preserve or remove the original properties。例如,教程Let's Make a Map 中的uk.json 文件中的特征和点具有name 属性。

【讨论】:

以上是关于使用 D3.js 仅渲染 topojson 地图的一部分的主要内容,如果未能解决你的问题,请参考以下文章

d3.js 地图:使用 geojson 文件和 CSV 数据

在 d3.js 地图中添加工具提示

将圆的半径(以米为单位)缩放到 D3.js d3.geo.mercator 地图

平滑 D3.js/GeoJSON/TopoJSON/Shapefile 中的弧线/绘图点(沿途某处)

D3.js 地理

地图没有在3d.js中渲染