地图中的圆圈在D3 V4中显示不正确的位置

时间:2017-07-12 21:08:49

标签: javascript d3.js svg geo map-projections

我正在使用教程来学习如何在D3.v3中生成地图,但我使用的是D3.v4。我只想让一些圆圈出现在地图上(见下文)。该代码的工作原理除了圈子在内华达州之外并且应该在湾区。我想这是地图投影和投影坐标之间的不匹配。我不确定地图的投影是什么,但我试图将它强制为albersUsa(请参阅注释掉我生成路径的命令),但这会导致整个地图消失。任何帮助将不胜感激!

<!DOCTYPE html>

<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>

var w = 960,
    h = 600;
var projection = d3.geoAlbersUsa();
var path = d3.geoPath()
             //.projection(projection)

d3.json("https://d3js.org/us-10m.v1.json", function(error, us) {
  if (error) throw error;

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

  svg.selectAll("path")
     .data(topojson.feature(us, us.objects.states).features)
     .enter().append("path")
	 .attr("class", "states")
     .attr("d", path);

   svg.append("path")
      .attr("class", "state-borders")
      .attr("d", path(topojson.mesh(us, us.objects.states)))

   svg.append("path")
      .attr("class", "county-borders")
      .attr("d", path(topojson.mesh(us, us.objects.counties)));

      aa = [-122.490402, 37.786453];
  	  bb = [-122.389809, 37.72728];

   svg.selectAll("circle")
      .data([aa,bb]).enter()
      .append("circle")
      .attr("cx", function (d) { return projection(d)[0]; })
      .attr("cy", function (d) { return projection(d)[1]; })
      .attr("r", "8px")
      .attr("fill", "red")
    });

</script>

1 个答案:

答案 0 :(得分:3)

您的US json已经投影,为了显示它您使用空投影:

var path = d3.geoPath()
             //.projection(projection)

如果不定义投影,您的topojson / geojson坐标将转换为直线像素坐标。碰巧这个特定的topojson文件的像素坐标在[0,0]和[960,600]之内,几乎与默认的bl.ock视图相同。如果不知道所使用的投影也会创建该文件,则无法复制该投影以将地理要素与数据对齐。 除非您直接使用像素值放置要素并完全跳过投影(对于不在可识别地标附近的点或精度很重要的点不起作用)。

当您使用geoUsaAlbers()进行投影时,您的美国topojson要素会消失,因为您正在平面上获取像素坐标并将它们转换为svg坐标,就像它们是三维地球上的点一样(d3投影需要纬度经度对) 。

相反,请使用未投影的topojson或geojson。也就是说它包含纬度/经度对并将数据与您的点一起投影。请参阅此bl.ock以获取使用代码的美国未投影(纬度/长对)json的示例(但将投影分配给path)。

要检查您是否拥有纬度/经度对,您可以轻松地在geojson文件中查看这些要素的几何,并查看这些值是否为有效的长点,纬度点。对于topojson,topojson库将要素转换为geojson,因此您可以在转换后查看几何。

以下是美国未经预料的topojson:https://bl.ocks.org/mbostock/raw/4090846/us.json

假设你真的想要使用相同的topojson文件,我们可以推断出它使用的投影。首先,我将展示您的投影点(通过使用未投影的美国轮廓)和投影的topojson(未投影的topojson投影为d3.geoAlbersUsa()和投影为空投影)之间的差异:

enter image description here

可能是投影d3.geoAlbersUsa针对bl.ocks.org默认视口960x500进行了优化。未投影的数据集有一个大约960x600的边界框,所以如果我们将比例增加600/500并调整平移,我们可以在960x600的svg中对齐我们的特征:

var projection = d3.geoAlbersUsa();   var scale = projection.scale()* 600/500;   projection.scale(刻度).translate([960/2600/2])   var projectedPath = d3.geoPath()。projection(projection);

而且,这似乎很好地对齐,我看不出两者之间的区别:

enter image description here

这是显示对齐功能的block

但正如我在评论中提到的那样,即使您可以对齐这些功能: 任何缩放或居中都会出现问题,因为您需要在已投影的数据上使用geoTransform,而在原始地理数据上使用geoProjection。使用所有(统一)投影数据或所有未投影数据可以简化生活。