D3.js d3js缩放、变换和转换

D3.js d3js缩放、变换和转换,d3.js,D3.js,我创建了一个使用angularJS(MVC)、yeoman(构建)、d3(映射)和geoJSON(地理数据)的项目 一切都很好,但我确实花了相当长的时间获得正确的规模和翻译。我想知道我如何能自动计算出地图在什么比例下会显示出它的最佳效果,以及平移中的x和y值是多少 'use strict'; japanAndCo2App.controller('MainCtrl', function($scope) { function makeJapanAll(){ var path, vis,

我创建了一个使用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();
});
(如果您对代码感兴趣,就这些。地图的代码与上面显示的相同。)

有一个示例,从geojson获取国家边界,然后将地图缩放并转换到该国家。代码有点难看;不过,今后仍有努力使这一点变得更容易(请参阅和)。

鉴于此:

xy = d3.geo.mercator().scale(someScale).translate([0, 0]);
someScale
使用墨卡托投影投影时整个世界的像素宽度。因此,如果您的json数据具有整个世界的轮廓–从lat/lng-180,90到latLng-180,-90–并且如果
someScale
为1024,那么世界将被绘制成完全适合1024x1024像素的正方形。这就是你在(嗯……有点……不太……继续阅读……)中看到的

但这还不够。当以1024px绘制世界时,不进行任何平移,lat/lng 0,0(即世界的“中间”)将位于投影地图的0,0像素处(即左上角)。在这些条件下,整个北半球和西半球的x或y值为负值,因此位于绘制区域之外。此外,在这些条件下,世界的右下角(即lat/lng-90180)将位于1024x1024正方形的正中间(即像素512512)

因此,为了将世界置于此处描述的正方形的中心,您需要将地图在X和Y方向平移一半宽度。也就是说,你需要

xy = d3.geo.mercator().scale(1024).translate([512, 512]);
这将为您提供我链接到的谷歌地图视图

如果您的json数据只有世界的一部分(如纽约州或纽约州),则使用此xy投影绘制它将在相对于整个1024x1024世界范围区域的正确地理位置渲染轮廓。所以它看起来很小,有很多空白


挑战在于如何缩放和平移投影,以使所讨论的区域填充1024x1024平方米。而且。。。到目前为止,我还没有回答这个问题,但我希望这个解释能为你指出正确的方向,让你明白这个数学。等我有更多时间的时候,我还会继续回答/

我也有同样的问题。但是,当您有一个边界框时,这是非常容易做到的,它可以通过GeoJSON(如meetamit所说)确定,或者在创建GeoJSON时确定。以及所需SVG的宽度

我将从geojson的边界框和图像尺寸的变量
lattop、lonleft、lonright、width
height
开始。我还没有用拉图度的差值计算出一个好的高度。因此,估计高度足够大,以适合图像。其余部分应在代码中明确:

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度),你必须考虑溢出量。

到目前为止运气好吗?我下载了你的github项目(也是bc,我想尝试一下yeoman)。很酷。你最近的承诺有纽约州地图,不是纽约市,但没关系。我试图找出你想要的数学框架,但结果比我想象的要复杂。我使用
d3.geo.bounds(json)
很容易地计算出被框定区域的边界,但是缩放和转换仍然让我难以理解。另外,@Lars Kotthoff的链接提供了一些方向,乍一看,这与我一直尝试的不同。是的,到目前为止,我发现的唯一配方是从100开始,你会得到一个小点,然后放大,同时以200的跳跃进行转换。根据你想要的地图有多大,大约需要10分钟才能把它弄对……询问@jasondavies是否有线索。谢谢分享lars。我看到Mike在结尾提到了“d3.geo.projection center(and rotate)”,我想这将在v3上解决这个问题。嘿,Sander17,谢谢你的评论。我还没想过这个包围盒,看起来很酷。我会试一试的。这对我不起作用。我使用的是d3.geo.albers()。代码是否依赖于投影?我必须使用哪种坐标来连接接线盒?我想我使用的是投影坐标……对于阿尔伯斯,我想它应该“几乎”起作用。图像的一部分可能超出svg的范围,但最大的部分应该是可见的。你能告诉我你用的坐标吗?你在哪个地区工作?