d3js缩放,转换和翻译

时间:2012-11-07 16:40:24

标签: d3.js

我创建了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,与上面显示的相同。)

3 个答案:

答案 0 :(得分:15)

我遇到了同样的问题。但是当你有一个边界框时很容易做到,这可以从GeoJSON(如meetamit所说)或创建GeoJson时确定。和想要的SVG的宽度。

我将从变量lattop, lonleft, lonright, widthheight开始,用于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获取国家/地区的边界,然后将地图缩放并转换为该国家/地区。代码有点难看;然而,将来会努力使这更容易(请参阅thisthis issue)。