我尝试使用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]);
我注意到的一件事是无论缩放级别如何,投影.invert()对于相同的[x,y]点(例如[1200,600]) 总是返回相同的lng / lat。此外,我所做的任何尝试都没有设法使[x,y]在不同的缩放级别保持不变,因此在翻译和缩放之外还有其他的东西在起作用。我怀疑它可能与投影有关,但我还没弄清楚是什么。
答案 0 :(得分:0)
在应用缩放后,我还没有找到从像素点到lng / lat坐标或从像素点到国家的方法。
话虽这么说,我发现了另一种效果也很好的方法。我列出了所有国家及其在lng / lat的质心。从该列表中,我解决了它们在像素中的位置,并根据比例和平移进行调整。最后,我发现哪一个最接近中心。这是代码:
closest: function() {
var p2 = [0,0];
var d = [width/2,height/2];
var scale = d3v3.event.scale;
var translate = d3v3.event.translate;
var min = Number.MAX_VALUE;
var minCountry = null;
for ( var key in this.centroids) {
var p1 = projection(this.centroids[key]);
p1[0]*=scale;
p1[1]*=scale;
p1[0]+=translate[0]-d[0];
p1[1]+=translate[1]-d[1];
var distance = Math.sqrt(Math.pow(p2[0] - p1[0],2) + Math.pow(p2[1] - p1[1],2));
if (distance < min) {
min = distance;
minCountry = key;
}
}
return [ minCountry, min ];
}