D3绘制空投影的经纬度图

3

d3.geo.path对象具有空投影,因为TopoJSON已经过投影处理,所以可以直接显示。我试图在地图上绘制形式为 [经度,纬度] 的数据。

以下是我的代码基本结构:

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
        ]) + ')';
    });

我调试过代码,确保数据获取正确。但是,我得到一个错误提示:“path([d.longitude, d.latitude])”未定义。“d”存在,并且包含经纬度值。“path”也存在。我认为是因为投影为空。

我该如何解决这个问题?

------- 编辑 ------- 根据Ben Lyall的建议,我删除了selectAll语句中的“path”,并将其移到了.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 +
            ')';
        });
});

------- EDIT ------- 解决方案是将Ben Lyall提出的解决方案与已经在地图上进行的.pin的投影相结合。由于代码中的投影为空,我不得不创建一个与地图投影相匹配的新投影,然后在对.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个回答

2
当您定位.pin元素时,为什么要在translate中使用path?您不希望创建路径,并且d.latituded.longitude值应该已经是像素坐标,因为它们已经被投影了,因此您应该能够直接使用它们。
注意:您可能还希望将代码的这部分放在d3.json处理程序内部,而不是外部,因为在您的数据设置为任何内容之前会异步运行(这可能是您代码实际遇到的问题,而不是错误地使用path)。
没有一个可以派生的示例有点难以确认,但可以尝试以下操作:
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 + ')';
        });
});

谢谢Ben!我更新了我的代码。这次我没有收到控制台错误,但是我仍然看不到地图上的任何标记。我更新了我的原始帖子。 - boombox
在这种情况下,您需要向我们展示一个示例,如果没有看到您的“ds”值,诊断将会很困难。 - Ben Lyall
这就是为什么我说你需要在问题中包含更多信息,特别是ds数组中的值。如果没有访问那些值,不确定你如何期望任何人回答该问题。 - Ben Lyall
从技术上讲,我们的回答都不能单独解决问题,projection 并不是你示例代码中唯一的问题,它还应用了 path,这也是不正确的。因此,两个答案的结合才是正确的。最好更新你的答案以包含这一点,但是你更新后的问题现在也有所有的信息来回答它,所以最好的行动方式就由你自己决定了。 - Ben Lyall
我认为将您的解决方案标记为正确是最好的选择。我通过在您提出的更改基础上构建它来得出了正确的解决方案。谢谢Ben。我在问题底部发布了之前发布的解决方案的代码。 - boombox
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接