D3绘制空投影的经度/纬度

Posted

技术标签:

【中文标题】D3绘制空投影的经度/纬度【英文标题】:D3 plotting longitude/latitude of null projection 【发布时间】:2015-06-18 05:23:43 【问题描述】:

d3.geo.path 的投影为空,因为 TopoJSON 已经投影,因此可以按原样显示。我正在尝试在地图上以 [longitude, latitude] 的形式绘制数据。

下面是我的代码基本上是这样的:

var width, height, path, svg;

width = 960;
height = 600;
path = d3.geo.path().projection(null);
svg = d3.select('.viz').append('svg')
    .attr('width', width)
    .attr('height', height);

d3.json("counties.json", function(error, us) 
    svg.append('path')
        .datum(topojson.mesh(us))
        .attr('d', path);
);

svg.selectAll('.pin')
    .data(ds) // i.e. ds = [12.521, 15.312], [616.122,-31.160]
    .enter().append('circle', '.pin')
    .attr('r', 3)
    .attr('transform', function (d) 
        return 'translate(' + path([
            d.longitude,
            d.latitude
        ]) + ')';
    );

我通过这个进行了调试,我确实得到了很好的数据。但是,我收到“路径([d.longitude,d.latitude])”未定义的错误。 “d”与经度和纬度值一起存在。 “路径”也存在。我认为这是因为投影为空。

我可以做些什么来完成这项工作?

------- 编辑 ------- 我按照 Ben Lyall 的建议删除了 selectAll 语句中“路径”的使用,并将 selectAll 语句移到了 .json() 中。我还注意到我为 ds 输入了一个错误的示例,所以我修改了评论。这是我更新的代码。

这可以很好地显示地图,没有控制台错误,但我仍然没有在地图本身中看到任何圆圈。

var width, height, path, svg;

width = 960;
height = 600;
path = d3.geo.path().projection(null);
svg = d3.select('.viz').append('svg')
    .attr('width', width)
    .attr('height', height);

d3.json("counties.json", function(error, us) 
    svg.append('path')
        .datum(topojson.mesh(us))
        .attr('d', path);

    svg.selectAll('.pin')
        .data(ds) // i.e. ds = [longitude: 12.521, latitude: 15.312, longitude: 616.122, latitude: -31.160]
        .enter().append('circle', '.pin')
        .attr('r', 3)
        .attr('transform', function (d) 
            return 'translate(' +
                d.longitude + ',' + d.latitude +
            ')';
        );
);

------- 编辑 ------- 该解决方案结合了 Ben Lyall 提出的解决方案,并考虑了在地图上已经为 .pins 完成的投影。由于代码中的投影为空,我必须创建一个与地图投影匹配的新投影,然后在对.pin 执行转换时使用它。

解决方法如下:

var width, height, path, projection, svg;

width = 960;
height = 600;
path = d3.geo.path().projection(null);
projection = d3.geo.albersUsa().scale(1280).translate([width/2, height/2]);
svg = d3.select('.viz').append('svg')
    .attr('width', width)
    .attr('height', height);

d3.json("counties.json", function(error, us) 
    svg.append('path')
        .datum(topojson.mesh(us))
        .attr('d', path);

    svg.selectAll('.pin')
        .data(ds)
        .enter().append('circle', '.pin')
        .attr('r', 3)
        .attr('transform', function (d) 
            return 'translate(' +
                projection([d.longitude, d.latitude]) +
            ')';
        );
);

【问题讨论】:

【参考方案1】:

当您定位.pin 元素时,为什么在translate 中使用path?您不想创建路径,d.latituded.longitude 值应该已经在像素坐标中,因为它们已经被投影,所以您应该能够直接使用它们。

注意:您可能还希望在 d3.json 处理程序中而不是在外部处理您的那部分代码,因为它会在您的数据设置为任何内容之前异步运行(这可能是您的代码的实际问题,而不是而不是错误地使用path)。

如果没有 fork 的例子,这有点难以确认,但试试这个:

var width, height, path, svg;

width = 960;
height = 600;
path = d3.geo.path().projection(null);
svg = d3.select('.viz').append('svg')
    .attr('width', width)
    .attr('height', height);

d3.json("counties.json", function(error, us) 
    svg.append('path')
        .datum(topojson.mesh(us))
        .attr('d', path);

    svg.selectAll('.pin')
        .data(ds) // i.e. ds = [12.521, 15.312], [616.122, -31.160]
        .enter().append('circle', '.pin')
        .attr('r', 3)
        .attr('transform', function (d)  
            return 'translate(' + d.longitude + "," + d.latitude + ')';
        );
);

【讨论】:

感谢本!我更新了我的代码。这次我没有收到控制台错误,但我仍然没有在地图上看到任何图钉。我更新了我原来的帖子。 在这种情况下,您将不得不向我们展示一个示例,而没有看到您的 ds 值是什么,这将很难诊断。 我发现问题不在于数据,而在于 .pin 的投影。 .pin 需要使用与地图相同的投影。我已经发布了解决方案。谢谢。 这正是我说您需要在问题中包含更多信息的原因,特别是您的 ds 数组中的值。不知道你会如何期望任何人在没有访问这些值的情况下回答这个问题。 感谢本的反馈。但是,我对您的评论感到困惑。我相信我提供了足够多的信息,但下次我会更加小心。我提供了示例值。事实是,你不需要知道 ds 中的实际值来知道我的代码出了什么问题,因为我使用的是空投影,因为 topojson 已经被投影。问题是 .pin 不知道要使用什么投影,而不是数据。这可以在我没有通过数据调试的情况下发现的代码中看到。感谢 Ben 提供的帮助。

以上是关于D3绘制空投影的经度/纬度的主要内容,如果未能解决你的问题,请参考以下文章

如何绘制 geoAlbersUsa() 投影的经纬度坐标?

如何在散景中绘制纬度和经度

在实时纬度和经度之间绘制路线

绘制经度和​​纬度

D3js:如何通过鼠标单击获取纬度/经度地理坐标?

在地图上围绕纬度/经度绘制时间半径