d3.js v5:无法获取在美国地图上显示的数据点

d3.js v5:无法获取在美国地图上显示的数据点,d3.js,geojson,topojson,D3.js,Geojson,Topojson,我可以成功地得到我们的地图来渲染,但我的数据点并没有。(我知道d3.js对v5做了一些重大更改,因此请注意,前面提出的类似问题不适用) })) 在这里可以找到一份工作副本 这里有很多问题: 将数据传递到数组 首先,当使用 svg.selectAll("circle") .data(meteoriteData) selectAll().data()要求您传递函数或数组。在您的情况下,您需要将数据数组传递给它-但是,meteoriteData是一个对象。它是一个geojson功能集合,具有以

我可以成功地得到我们的地图来渲染,但我的数据点并没有。(我知道d3.js对v5做了一些重大更改,因此请注意,前面提出的类似问题不适用)

}))


在这里可以找到一份工作副本

这里有很多问题:

将数据传递到数组 首先,当使用

svg.selectAll("circle")
   .data(meteoriteData)
selectAll().data()
要求您传递函数或数组。在您的情况下,您需要将数据数组传递给它-但是,
meteoriteData
是一个对象。它是一个geojson功能集合,具有以下结构:

{
  "type": "FeatureCollection",
  "features": [
      /* features */
  ]
}
所有单独的geojson功能都位于该对象内的一个数组中。要获取特征数组,在本例中,表示流星的特征,我们需要使用:

svg.selectAll("circle")
   .data(meteoriteData.features)
现在,我们可以为特征集合中的每个特征创建一个圆。如果执行此操作,则在检查SVG元素时可以找到圆圈,但它们不会正确放置


定位点 如果进行上述更改,您将无法在正确的位置看到圆圈。您没有在此处正确定位圆:

 .attr("cx", function (d) { return ([d.geometry.coordinates[0], d.geometry.coordinates[1]])[1]; })
这与:

 .attr("cx", function(d) { return d.geometry.coordinates[1]; })
这里有两个问题:第一,geojson是
[经度,纬度]
,或者
[x,y]
(您在这里获得的是y坐标,但设置的是x值)

但是,更大的问题是你没有预测你的数据。这是geojson中的原始坐标:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      -113,
      54.21667
    ]
   ...
您正在获取经度并直接将其转换为像素值。但geojson使用的是三维坐标空间(三维球体上的未投影点),单位以度为单位。如果我们简单地将其转换为像素,
cx=-113
,您的圆圈将显示在SVG左侧的屏幕外

使用投影 您需要投影数据,为此,我们将定义一个投影函数,并使用如下内容:

  .attr("cx", function(d) { return projection(d.geometry.coordinates)[0] })
这将获取经度和纬度并将其传递给投影函数,然后获取返回的x值并将其设置为cx的值

投影以度为单位获取三维空间中的未投影坐标(球体上的点或长/宽对),并返回以像素为单位的二维空间中的点

但是,现在我们要面对最困难的部分:

你应该使用什么投影

我们需要将我们的点与已经绘制的美国特征对齐,但您不为美国各州定义投影-如果您不向d3.geoPath提供投影,它将使用空投影,它将获取提供的坐标并将其绘制在SVG上,就像它们是像素坐标一样。不发生转换。我知道你的美国特征是投影的,因为阿拉斯加不是它应该在的地方,地形图中的坐标值经度超过+/-180度,纬度超过+/-90度,地图看起来像是用阿尔伯斯投影投影的

如果geoPath没有使用d3投影来投影数据,但数据是像投影一样绘制的,则数据是预投影的-此topojson存储已投影的点

我们有预测数据(美国各州)和未预测数据(流星撞击),将它们混合在一起总是一个挑战

这里的挑战是创建一个投影,复制用于创建美国各州数据集的投影函数。我们可以复制这个投影,因为它是一个有问题的文件,导致了许多问题。解释了如何做到这一点。但这比实际情况更为复杂:混合预测数据和未预测数据是一项繁重、不灵活的工作,而且比实际需要更为复杂

我建议您使用美国和流星的未投影数据:

var projection = d3.geoAlbersUsa();             // create an Albers USA projection
var path = d3.geoPath().projection(projection); // set the projection for the path
我们可以用同样的方法绘制路径,前提是我们找到美国的未投影topojson/geojson,并且我们可以用以下方式放置点:

.attr("cx", function(d) { return projection(d.geometry.coordinates)[0]; })
.attr("cy", function(d) { return projection(d.geometry.coordinates)[1]; })
至于找到一个未被投射的美国,那是一个


这里是一个使用上述方法并投影所有数据的例子(我还过滤特征以去除没有坐标的特征,那些美国阿尔伯斯可能会破坏的特征,因为这是一个复合投影)。

感谢您如此透彻@Andrew Reid。它的工作与陨石数据伟大。然而,当我用从本地数据库获得的格式相同的数据集替换陨石数据时,它仍然不起作用。数据正在返回,但未反映在地图上。我怀疑这可能是dom在返回数据之前呈现的b/c。有没有办法使用Promise.all功能来控制这一点?
.attr("cx", function(d) { return projection(d.geometry.coordinates)[0]; })
.attr("cy", function(d) { return projection(d.geometry.coordinates)[1]; })