我制作了以下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>
在我的答复中,由于自d3v4起包含了有助于绘制此数据的新功能(例如d3.geoIdentity
,projection.fitSize
),因此我将所有代码都升级到d3v5。从D3 v4开始,对D3名称空间进行了一些更改(d3.geo.path和d3.geo.projectionName
现在为d3.geoPath
和d3.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范围不匹配,则该选项将无用。相反,我们可以使用geoTransform
或geoIdentity
进行适当的变换。
geoIdentity
选项是最简单的,因为它提供了方便的fitSize
方法,该方法使我们可以自动将geojson调整为SVG / Canvas尺寸(fitExtent
允许指定边距,而fitSize
假定没有边距) 。所有这些选项都可以作为投影传递到d3.geoPath(example,full screen)。
最后一个示例应显示如何绘制数据。您通常都有线串,除非您只想显示边框,否则这将使填充功能变得困难。
进一步阅读
根据以前的经验,我想到了一些相关的问题:
此问题解决了关于预投影几何图形的可能问题,因为您似乎已经为屏幕尺寸预投影了几何图形。这带来了对齐挑战,需要权衡的是更快的渲染时间。
此问题涉及预投影的几何形状以及将特征拟合到屏幕上的问题。它更深入地讲fitSize
,fitExtent
和geoTransform
。