加载 topojson 文件时出现随机行?
Random lines when loading topojson file?
我正在尝试使用 d3 加载我的安大略地图的 topojson 文件,但我得到的只是一堆随机行,就像 一样。
我的文件使用的是 WGS84,所以这也不是问题所在。我究竟做错了什么?下面的js代码。
var width = 960, height = 700;
var svg = d3.select('#map').append('svg')
.attr('width', width)
.attr('height', height)
d3.json('CensusSubDiv.json', function(error, CensusSubDiv) {
if (error) return console.error(error);
svg.append('path')
.datum(topojson.feature(CensusSubDiv, CensusSubDiv.objects.CensusSubDivision))
.attr('d', d3.geo.path().projection(d3.geo.mercator()))
.attr('id', 'ont')
;
});
因此,正如我在评论中提到的,您的数据可能使用 WGS84 作为基准,但 D3 要求将 WGS84 用作 "projection"(d3 需要纬度和经度,它们代表三坐标上的点维度球体,因此实际上是未投影的,因此是我的引述)。因此,投影数据有时会标有 WGS84 以及其他标识符。
好消息是您可以相当轻松地显示投影数据 - 好消息 。我们不做三维数学,而是在绘制数据之前转换和缩放数据。坏消息是这对 d3 v4 最有效(我的示例使用了它,它只改变了几点:例如:d3.geo.path
-> d3.geoPath
,d3.geo.projection
- > d3.geoProjection
, 等等).
由于您的数据已经投影,我们可以使用 d3.geoIdentity
,这允许我们使用 projection.fitSize()
(修改比例和平移)方法,但不投影数据。 FitSize 为显示区域的 width/height 获取一个数组和一个 geojson 对象:
projection.fitSize([width,height],geojsonObject)
fitSize 不是 d3v3 的一部分,但我们在 d3v5 上,所以更新不是坏事,projection.fitExtent 允许边距
与SVG坐标space一样,Y值从屏幕顶部的0开始,随着向下移动而增加,而在大多数投影坐标spaces中,Y值从屏幕顶部开始地图底部,随着向北移动而增加,我们还需要在y轴上翻转身份:
var projection = d3.geoIdentity()
.reflectY(true)
.fitSize([width,height],geojsonObject)
这使我们能够相当轻松地显示数据。请参阅 this block 了解具有上述更改的数据。
但是,这里有一个警告,你有已经投影的数据,如果你不知道这些数据是如何投影的,你就不能对齐其他未投影或以其他方式投影的地理数据:你不能使用给定的经度纬度投影一个点,因为您不知道如何以与已投影数据相同的方式对其进行投影。
这可能不是问题,例如在等值区中,您可能只需要人口普查分区的轮廓。但是,如果您想将城市放在地图的顶部,如果这些城市的坐标尚未以与人口普查数据相同的方式投影,您将面临一些困难。
如果您想在安大略省覆盖其他地理数据(未投影数据),则需要取消投影您的数据。在 mapshaper 中,当您最初将数据导入 window 时(确保您也拖动了 .prj 文件 - 否则 mapshaper 将不知道从哪个投影重新投影数据),您可以打开控制台并键入 proj WGS84
,这应该为您提供以度为单位的坐标(尽管 topojson 仍将具有编码的整数坐标,如果导出到 geojson,坐标将以纯文本形式存储)。当然,如果您选择取消投影数据,则需要再次使用更典型的投影,例如 d3.geoMercator()。
我正在尝试使用 d3 加载我的安大略地图的 topojson 文件,但我得到的只是一堆随机行,就像
我的文件使用的是 WGS84,所以这也不是问题所在。我究竟做错了什么?下面的js代码。
var width = 960, height = 700;
var svg = d3.select('#map').append('svg')
.attr('width', width)
.attr('height', height)
d3.json('CensusSubDiv.json', function(error, CensusSubDiv) {
if (error) return console.error(error);
svg.append('path')
.datum(topojson.feature(CensusSubDiv, CensusSubDiv.objects.CensusSubDivision))
.attr('d', d3.geo.path().projection(d3.geo.mercator()))
.attr('id', 'ont')
;
});
因此,正如我在评论中提到的,您的数据可能使用 WGS84 作为基准,但 D3 要求将 WGS84 用作 "projection"(d3 需要纬度和经度,它们代表三坐标上的点维度球体,因此实际上是未投影的,因此是我的引述)。因此,投影数据有时会标有 WGS84 以及其他标识符。
好消息是您可以相当轻松地显示投影数据 - 好消息 d3.geo.path
-> d3.geoPath
,d3.geo.projection
- > d3.geoProjection
, 等等).
由于您的数据已经投影,我们可以使用 d3.geoIdentity
,这允许我们使用 projection.fitSize()
(修改比例和平移)方法,但不投影数据。 FitSize 为显示区域的 width/height 获取一个数组和一个 geojson 对象:
projection.fitSize([width,height],geojsonObject)
fitSize 不是 d3v3 的一部分,但我们在 d3v5 上,所以更新不是坏事,projection.fitExtent 允许边距
与SVG坐标space一样,Y值从屏幕顶部的0开始,随着向下移动而增加,而在大多数投影坐标spaces中,Y值从屏幕顶部开始地图底部,随着向北移动而增加,我们还需要在y轴上翻转身份:
var projection = d3.geoIdentity()
.reflectY(true)
.fitSize([width,height],geojsonObject)
这使我们能够相当轻松地显示数据。请参阅 this block 了解具有上述更改的数据。
但是,这里有一个警告,你有已经投影的数据,如果你不知道这些数据是如何投影的,你就不能对齐其他未投影或以其他方式投影的地理数据:你不能使用给定的经度纬度投影一个点,因为您不知道如何以与已投影数据相同的方式对其进行投影。
这可能不是问题,例如在等值区中,您可能只需要人口普查分区的轮廓。但是,如果您想将城市放在地图的顶部,如果这些城市的坐标尚未以与人口普查数据相同的方式投影,您将面临一些困难。
如果您想在安大略省覆盖其他地理数据(未投影数据),则需要取消投影您的数据。在 mapshaper 中,当您最初将数据导入 window 时(确保您也拖动了 .prj 文件 - 否则 mapshaper 将不知道从哪个投影重新投影数据),您可以打开控制台并键入 proj WGS84
,这应该为您提供以度为单位的坐标(尽管 topojson 仍将具有编码的整数坐标,如果导出到 geojson,坐标将以纯文本形式存储)。当然,如果您选择取消投影数据,则需要再次使用更典型的投影,例如 d3.geoMercator()。