D3 绘制 longitude/latitude 的空投影
D3 plotting longitude/latitude of null projection
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
]) + ')';
});
我调试通过这个,我确实得到了数据。但是,我收到 "path([d.longitude, d.latitude])" 未定义的错误。 "d" 存在经度和纬度值。 "path" 也存在。我认为这是因为投影为空。
我该怎么做才能完成这项工作?
--------编辑------
我遵循了 Ben Lyall 的建议,删除了 selectAll 语句中 "path" 的使用,并将 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 提出的解决方案,并考虑了已经在地图上为 .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]) +
')';
});
});
当您定位 .pin
元素时,为什么要在 translate
中使用 path
?您不想创建路径,并且 d.latitude
和 d.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 + ')';
});
});
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
]) + ')';
});
我调试通过这个,我确实得到了数据。但是,我收到 "path([d.longitude, d.latitude])" 未定义的错误。 "d" 存在经度和纬度值。 "path" 也存在。我认为这是因为投影为空。
我该怎么做才能完成这项工作?
--------编辑------ 我遵循了 Ben Lyall 的建议,删除了 selectAll 语句中 "path" 的使用,并将 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 提出的解决方案,并考虑了已经在地图上为 .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]) +
')';
});
});
当您定位 .pin
元素时,为什么要在 translate
中使用 path
?您不想创建路径,并且 d.latitude
和 d.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 + ')';
});
});