【发布时间】:2015-01-08 18:59:45
【问题描述】:
我正在尝试使用 d3 确定地图上像素点的坐标。最终目标是确定哪些国家目前在地图上可见。 这是我正在使用的代码:
method: function() {
var e = $("#" + this.getView().getId());
if (!e || e.length === 0) {
return;
}
this.width = e.width();
this.height = e.height();
this.topojson = window.topojson;
var width = this.width;
var height = this.height;
var centered;
var d3v3 = window.d3v3;
var projection = d3v3.geo.mercator()
.translate([width / 2, height / 2]);
var path = d3v3.geo.path()
.projection(projection);
var svg = d3v3.select("#" + this.byId("map").getId());
svg.selectAll("g").remove();
svg
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
d3v3.json(getPath("/110m_admin_0.json"), function(us) {
g.append("g")
.attr("id", "states")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects["110m_admin_0_"]).features)
.enter().append("path")
.attr("d", path)
.attr("class", function(d) { return "q"+(Math.floor((Math.random() * 9) + 0)) + "-9"; });
});
var zoom = d3v3.behavior.zoom()
.on("zoom",$.proxy(function() {
var width1 = width/2;
var height1 = height/2;
var xt1 = d3v3.event.translate[0];
var yt1 = d3v3.event.translate[1];
var x = xt1;
var y = yt1;
x+=width1;
y+=height1;
var proj = projection.invert([x,y]);
proj[0]*=-1;
proj[1]*=-1;
var closestCountry = this.closestCountry(proj);
console.log(d3v3.event.scale + " | " + [x,y] + " | " + proj + " | " + closestCountry );
g.attr("transform","translate("+
d3v3.event.translate.join(",")+")scale("+d3v3.event.scale+")");
g.selectAll("path")
.attr("d", path.projection(projection));
},this));
svg.call(zoom);
}
此代码在缩放级别为 1 时有效,但在缩放级别更改时立即失败。
这是我尝试过的一些变体。
1)
var x = d3v3.event.translate[0];
var y = d3v3.event.translate[1];
x+=width/2;
y+=height/2;
var proj = projection.invert([x,y]);
2)
var x = d3v3.event.translate[0]/d3v3.event.scale;
var y = d3v3.event.translate[1]/d3v3.event.scale;
x+=width/2;
y+=height/2;
var proj = projection.invert([x,y]);
3)
var x = d3v3.event.translate[0];
var y = d3v3.event.translate[1];
x+=width/2*d3v3.event.scale;
y+=height/2*d3v3.event.scale;
var proj = projection.invert([x,y]);
4)
var x = d3v3.event.translate[0]/d3v3.event.scale;
var y = d3v3.event.translate[1]/d3v3.event.scale;
x+=width/2*d3v3.event.scale;
y+=height/2*d3v3.event.scale;
var proj = projection.invert([x,y]);
我注意到的一件事是,无论缩放级别如何,针对相同 [x,y] 点(例如 [1200,600])的 projection.invert() 总是返回相同的 lng/lat。此外,我所做的任何尝试都没有设法使 [x,y] 在不同的缩放级别上保持不变,因此除了平移和缩放之外,这里还有其他东西在起作用。我怀疑它可能与投影有关,但我仍然没有弄清楚是什么。
【问题讨论】:
-
在进行 projection.invert() 之前,您需要考虑缩放和平移作为缩放的结果。您可以从缩放对象中检索这两者,因此您应该能够除以比例并平移缩放平移的反向以转换回默认像素坐标,然后可以将其传递给 projection.invert()
-
@BenLyall 谢谢你的评论。我已根据您的评论编辑了我的问题。
-
现在我有更多的时间来思考和调查,您可以使用投影的内置 .translate() 和 .scale() 方法来完成为你工作。您可以查看bl.ocks.org/mbostock/2206340,看看它是否适合您。您应该能够更新投影的比例并从缩放行为转换,然后使用 projection.invert() 从像素位置获取纬度/经度。