D3.geo:给定 geojson 对象的响应框架?

D3.geo : responsive frame given a geojson object?

我使用 Mike Bostock 的代码 Center a map in d3 given a geoJSON object

代码的重要部分是这样的:

var width = 960,
    height = 500;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("/d/4090846/us.json", function(error, us) {
  var states = topojson.feature(us, us.objects.states),
      state = states.features.filter(function(d) { return d.id === 34; })[0];

/* ******************* AUTOCENTERING ************************* */
// Create a unit projection.
var projection = d3.geo.albers()
    .scale(1)
    .translate([0, 0]);

// Create a path generator.
var path = d3.geo.path()
    .projection(projection);

// Compute the bounds of a feature of interest, then derive scale & translate.
var b = path.bounds(state),
    s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
    t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

// Update the projection to use computed scale & translate.
projection
    .scale(s)
    .translate(t);
/* ******************* END *********************************** */

// Landmass
  svg.append("path")
      .datum(states)
      .attr("class", "feature")
      .attr("d", path);

// Focus 
  svg.append("path")
      .datum(state)
      .attr("class", "outline")
      .attr("d", path);
});

例如,bl.ocks.org/4707858放大这样:

如何在目标上居中和缩放 topo/geo。json 并调整 svg 框架尺寸,使其适合每个尺寸的 5% 边距?

迈克的解释

基本上,Mike 的代码通过

说明了框架尺寸
var width = 960, height = 500;
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

一旦框架几乎没有设置,然后你检查最大限制比所以你的geojson形状填充你的svg框架相对于svg框架尺寸的最大尺寸widht &高度。也就是说,如果形状的宽度 VS 框架宽度或形状高度 VS 框架高度是最高的。反过来,这有助于通过 1/highest ratio 重新计算比例,使形状尽可能小。全部通过以下方式完成:

var b = path.bounds(state),
    s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
// b as [[left, bottom], [right, top]]
// (b[1][0] - b[0][0]) = b.left - b.right = shape's width
// (b[1][3] - b[0][4]) = b.top - b.bottom = shape's height

然后,刷新你的比例和过渡你得到 Mike Bostock's zoom:

新框架

围绕geojson 形状进行框框实际上是对Mike 代码的简化。首先,设置临时 svg 尺寸:

var width = 200;
var svg = d3.select("body").append("svg")
    .attr("width", width);

然后,获取形状的尺寸并围绕它进行计算:

var b = path.bounds(state);
    // b.s = b[0][1]; b.n = b[1][1]; b.w = b[0][0]; b.e = b[1][0];
    b.height = Math.abs(b[1][1] - b[0][1]); b.width = Math.abs(b[1][0] - b[0][0]);
var r = ( b.height / b.width );
var s = 0.9 / (b.width / width);                                // dimension of reference: `width` (constant)
//var s = 1 / Math.max(b.width / width, b.height / height );    // dimension of reference: largest side.
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (width*r - s * (b[1][1] + b[0][1])) / 2]; //translation

刷新投影和svg的高度:

 var proj = projection
      .scale(s)
      .translate(t);
  svg.attr("height", width*r);

完成,适合 pre-allocated width=150px,找到所需的高度,并适当缩放。 参见 http://bl.ocks.org/hugolpz/9643738d5f79c7b594d0