我正在使用教程来学习如何在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>
解决方法:
您的US json已经被投影,要显示它,请使用null投影:
var path = d3.geoPath()
//.projection(projection)
在不定义投影的情况下,您的topojson / geojson坐标将转换为直线像素坐标.碰巧这个特殊的topojson文件的像素坐标在[0,0]和[960,600]之内,几乎与默认的bl.ock视图大小相同.在不知道所使用的投影也无法创建该文件的情况下,您无法复制该投影以使地理特征与数据对齐.除非您直接使用像素值放置要素并完全跳过投影(这对于不在可识别地标附近或精度很重要的点没有用).
使用geoUsaAlbers()进行投影时,您的美国topojson功能会消失,因为您正在平面上获取像素坐标并将其转换为svg坐标,就好像它们是三维地球上的点一样(d3投影需要纬度经度对).
相反,请使用未投影的topojson或geojson.也就是说,它包含纬度/经度对,并将这些数据与您的点一起投影.有关使用代码在美国使用未投影(经纬度对)json的示例,请参见此bl.ock(但将投影分配给路径).
要检查您是否有纬度/经度对,可以轻松地在geojson文件中查看这些要素的几何形状,并查看这些值是否为有效的经纬度点.对于topojson,topojson库会将要素转换为geojson,因此您可以在此转换后查看几何.
这是美国的非预期topojson:https://bl.ocks.org/mbostock/raw/4090846/us.json
假设您确实想使用相同的topojson文件,那么我们很可能可以推断出它使用的投影.首先,我将显示您的投影点(通过使用美国的未投影轮廓)和投影的topojson(未投影的topojson使用d3.geoAlbersUsa()投影且使用零投影的投影)之间的差异:
投影d3.geoAlbersUsa可能会针对bl.ocks.org默认视口960×500进行优化.未投影的数据集的边界框大约为960×600,因此,如果我们将缩放比例增加600/500并调整平移,我们可以在960×600的svg中对齐要素:
var projection = d3.geoAlbersUsa();
var scale = projection.scale()* 600/500;
projection.scale(scale).translate([960 / 2,600 / 2])
var projectedPath = d3.geoPath().projection(projection);
而且,这似乎对齐得很好,我看不到两者之间的区别:
这是显示对齐特征的block.
但是正如我在评论中提到的那样,即使您可以对齐特征:
任何缩放或居中都会有问题,因为您需要在已投影的数据上使用geoTransform,而在原始地理数据上使用geoProjection.使用所有(统一)投影数据或所有非投影数据可以简化工作.