让我们制作一个TopoJSON映射并使用D3.js进行查看

问题描述 投票:1回答:1

我制作了以下TopoJSON文件:https://gofile.io/d/CKBGhF

我想用基本的D3.js脚本在浏览器中查看它。从https://bost.ocks.org/mike/map/中,我找到了一个有关脚本的小教程。但是因为我的地图是由转换为TopoJSON的向量制成的,所以它没有真实的坐标。使用QGIS,我首先将其保存为GeoJSON,使用mapshaper将其保存为TopoJSON。

我应该如何查看我的地图?坐标或缩放比例是否完全错误?还是我的TopoJSON不好?

我的HTML / JavaScript代码(我只更改了文件名):

<!DOCTYPE html>
<meta charset="utf-8">
<style>

/* CSS goes here. */

</style>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>

var width = 960,
    height = 1160;

var projection = d3.geo.mercator()
    .scale(500)
    .translate([width / 2, height / 2]);

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

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

d3.json("topojson_mapshaper.json", function(error, uk) {
  svg.append("path")
      .datum(topojson.feature(uk, uk.objects.subunits))
      .attr("d", path);
});

</script>
d3.js geojson topojson
1个回答
0
投票

在我的答复中,由于自d3v4起包含了有助于绘制此数据的新功能(例如d3.geoIdentityprojection.fitSize),因此我将所有代码都升级到d3v5。从D3 v4开始,对D3名称空间进行了一些更改(d3.geo.path和d3.geo.projectionName现在为d3.geoPathd3.geoProjectionName)。在D3v5中,d3.json现在返回promise。

这里有几件事在起作用。

Topojson.feature

[首先,D3仅使用d3.geoPath绘制geojson对象,D3不直接绘制topojson。因此,您的数据在存储为topojson的同时,会在此处转换为geojson:

topojson.feature(uk, uk.objects.subunits)

但是您的topojson数据uk没有包含功能的subunits属性。相反,您有一个名为test的子单元属性:

 ...463908,4.10162]},"objects":{"test":{"type":"GeometryCollection"...

通常,诸如mapshaper之类的平台将源文件的文件名用作子属性名称,因此我猜测从QGIS导出的源文件是test.geojson或类似的东西。

如果我们登录:

console.log(topojson.feature(uk, uk.objects.test))

我们看到有效的geojson。现在有了geojson,我们可以绘制它了。

坐标

对于坐标系,topojson默认保留原始坐标系。转换回geojson时,您的坐标将与原始坐标相同。因此,除非您的源数据没有实际坐标,否则“没有实际坐标”这一说法是不正确的。

但是,您可以在生成topojson时从命令行或使用mapshaper投影或重新投影点。看来您已经在点上应用了投影,因为当我将topojson转换为geojson时,我看到的坐标看起来像像素值(不太可能是从QGIS导出的原始坐标的单位)。

[如果使用投影坐标(笛卡尔点,不是长对,无论是米还是像素),我们将无法使用D3 geoProjection:这些投影采用3D点并将它们投影到平面上。

由于您的值看起来像像素值,因此我们可以将您的数据直接传递到null投影:

var path = d3.geoPath()

或更明确地说:

var path = d3.geoPath(null);
var path = d3.geoPath().projection(null);

在D3v3及更早版本中,需要显式设置

这不会对geojson中的坐标进行任何变换。它将每个geojson坐标视为一个像素坐标,并相应地绘制您的特征(example

但是,如果我们的功能的预计范围与SVG / Canvas范围不匹配,则该选项将无用。相反,我们可以使用geoTransformgeoIdentity进行适当的变换。

geoIdentity选项是最简单的,因为它提供了方便的fitSize方法,该方法使我们可以自动将geojson调整为SVG / Canvas尺寸(fitExtent允许指定边距,而fitSize假定没有边距) 。所有这些选项都可以作为投影传递到d3.geoPath(examplefull screen)。

最后一个示例应显示如何绘制数据。您通常都有线串,除非您只想显示边框,否则这将使填充功能变得困难。

进一步阅读

根据以前的经验,我想到了一些相关的问题:

此问题解决了关于预投影几何图形的可能问题,因为您似乎已经为屏幕尺寸预投影了几何图形。这带来了对齐挑战,需要权衡的是更快的渲染时间。

此问题涉及预投影的几何形状以及将特征拟合到屏幕上的问题。它更深入地讲fitSizefitExtentgeoTransform

© www.soinside.com 2019 - 2024. All rights reserved.