Center a map in d3 given a geoJSON object Ask Question

Center a map in d3 given a geoJSON object Ask Question

Currently in d3 if you have a geoJSON object that you are going to draw you have to scale it and translate it in order to get it to the size that one wants and translate it in order to center it. This is a very tedious task of trial and error, and I was wondering if anyone knew a better way to obtain these values?

So for instance if I have this code

var path, vis, xy;
xy = d3.geo.mercator().scale(8500).translate([0, -1200]);

path = d3.geo.path().projection(xy);

vis = d3.select("#vis").append("svg:svg").attr("width", 960).attr("height", 600);

d3.json("../../data/ireland2.geojson", function(json) {
  return vis.append("svg:g")
    .attr("class", "tracts")
    .selectAll("path")
    .data(json.features).enter()
    .append("svg:path")
    .attr("d", path)
    .attr("fill", "#85C3C0")
    .attr("stroke", "#222");
});

少しずつ進めずに、.scale(8500) と .translate([0, -1200]) を取得するにはどうしたらいいのでしょうか?

ベストアンサー1

私の答えは Jan van der Laan の答えに近いですが、地理的な重心を計算する必要がなく、境界ボックスだけが必要なので、少し簡略化できます。また、スケールなし、変換なしの単位投影を使用することで、計算を簡略化できます。

コードの重要な部分は次のとおりです。

// 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);

フィーチャーの境界ボックス単位投影では、適切な規模バウンディング ボックスのアスペクト比 (b[1][0] - b[0][0]およびb[1][1] - b[0][1]) とキャンバスのアスペクト比 (widthおよびheight) を比較します。この場合、バウンディング ボックスをキャンバスの 100% ではなく 95% に拡大縮小したので、端にストロークや周囲の特徴、またはパディングのための余裕が少しあります。

次に、翻訳する境界ボックスの中心 ((b[1][0] + b[0][0]) / 2および(b[1][1] + b[0][1]) / 2) とキャンバスの中心 (width / 2およびheight / 2) を使用します。境界ボックスは単位投影の座標にあるため、スケール ( s) を掛ける必要があることに注意してください。

例えば、bl.ocks.org/4707858:

境界ボックスに投影する

関連する質問として、投影を調整せずにコレクション内の特定のフィーチャにズームする方法があります。つまり投影と幾何学的変換を組み合わせてズームインとズームアウトします。これは上記と同じ原理を使用しますが、幾何学的変換 (SVG の "transform" 属性) が地理投影と組み合わされているため、計算が若干異なります。

例えば、bl.ocks.org/4699541:

境界ボックスにズーム

おすすめ記事