我创建了nycMap,这是一个使用angularJS(MVC),yeoman(构建),d3(映射)和geoJSON(地理数据)的项目。
一切都很好,但我确实需要花一些时间来获得正确的比例和翻译。我想知道如何自动确定地图将以何种比例展示最佳状态以及x和y值在翻译中的含义?
'use strict';
japanAndCo2App.controller('MainCtrl', function($scope) {
function makeJapanAll(){
var path, vis, xy;
xy = d3.geo.mercator().scale(16000).translate([-5600,2200]);
path = d3.geo.path().projection(xy);
vis = d3.select("#japanAll").append("svg:svg").attr("width", 1024).attr("height", 700);
d3.json("data/JPN_geo4.json", function(json) {
return vis.append("svg:g")
.attr("class", "tracts")
.selectAll("path")
.data(json.features).enter()
.append("svg:path")
.attr("d", path)
.attr("fill",function(d,i){ return d.properties.color || "transparent"});
});
}
makeJapanAll();
});
(如果您对代码感兴趣,则全部为on github。地图代码位于scripts/controllers/main.js,与上面显示的相同。)
答案 0 :(得分:15)
我遇到了同样的问题。但是当你有一个边界框时很容易做到,这可以从GeoJSON(如meetamit所说)或创建GeoJson时确定。和想要的SVG的宽度。
我将从变量lattop, lonleft, lonright, width
和height
开始,用于geojson的边界框和图像的尺寸。我还没有从latutude的差异中计算出一个好的高度。因此估计高度足以适应图像。其余部分应该从代码中清楚:
var xym = d3.geo.mercator();
// Coordinates of Flanders
var lattop = 51.6;
var lonleft = 2.4;
var lonright = 7.7;
var width = 1500;
var height =1000;
// make the scale so that the difference of longitude is
// exactly the width of the image
var scale = 360*width/(lonright-lonleft);
xym.scale(scale);
// translate the origin of the map to [0,0] as a start,
// not to the now meaningless default of [480,250]
xym.translate([0,0]);
// check where your top left coordinate is projected
var trans = xym([lonleft,lattop]);
// translate your map in the negative direction of that result
xym.translate([-1*trans[0],-1*trans[1]]);
var path = d3.geo.path().projection(xym);
var svg = d3.select("body").append("svg").attr("width",width).attr("height",height);
注意,如果你越过日期线(180度),你将不得不考虑溢出。
答案 1 :(得分:7)
鉴于此:
xy = d3.geo.mercator().scale(someScale).translate([0, 0]);
使用墨卡托投影 someScale
投影时整个世界的像素宽度。所以,如果你的json数据有整个世界的轮廓 - 从lat / lng -180,90到latLng 180,-90 - 如果someScale
是1024,那么将绘制世界,使其完全适合在1024x1024像素的正方形内。这就是你在this Google Maps view中所看到的(好吧......有点......不太......继续阅读......)。
但这还不够。当世界以1024px绘制而没有任何平移时,lat / lng 0,0(即世界的“中间”)将位于投影地图的0,0像素(即左上角)。在这些条件下,整个北半球和西半球都有负x或y值,因此落在绘制区域之外。此外,在这些条件下,世界的右下角(即lat / lng -90,180)将位于1024x1024平方的正中间(即像素512,512)。
因此,为了将世界置于此处描述的方格中心,您需要在X和Y方向上translate
将地图宽度减半。即你需要
xy = d3.geo.mercator().scale(1024).translate([512, 512]);
这将为您提供我链接到的Google地图视图。
如果您的json数据仅包含世界的一部分(例如,nyc或NY州),则使用此xy投影绘制它将使相对于整个1024x1024世界范围区域的正确地理位置呈现轮廓。所以看起来很小,有很多空白。
挑战在于如何缩放和翻译投影,使得所涉及的区域填满1024x1024平方。而且...到目前为止我还没有回答这个问题,但我希望这个解释能指出你正确的方向来计算这个数学。当我有更多时间时,我也会尝试继续回答。 :/
答案 2 :(得分:0)
有一个示例here从geojson获取国家/地区的边界,然后将地图缩放并转换为该国家/地区。代码有点难看;然而,将来会努力使这更容易(请参阅this和this issue)。