Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
631 views
in Technique[技术] by (71.8m points)

dictionary - D3.geo : responsive frame given a geojson object?

I use Mike Bostock's code to Center a map in d3 given a geoJSON object.

The important part of the code is this:

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

For example, bl.ocks.org/4707858 zoom in such:

project to bounding box

How to center and zoom on the target topo/geo.json AND adjust the svg frame dimensions so it fit a 5% margin on each size ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Mike's explained

Basically, Mike's code states the frame dimensions via

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

Once the frame is hardly set, then you check out the largest limiting ratio so your geojson shape fill your svg frame on its largest dimension relative to the svg frame dimensions widht & height. Aka, if the shape's width VS frame width or shape height VS frame height is the highest. This, in turn, help to recalculate the scale via 1/highest ratio so the shape is as small as required. It's all done via:

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

Then, refreshing your scale and transition you get Mike Bostock's zoom:

project to bounding box

New framing

To frame up around the geojson shape is actually a simplification of Mike's code. First, set temporary svg dimensions:

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

Then, get the dimensions of the shapes and compute around it :

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

Refresh projection and svg's height:

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

It's done and fit the pre-allocated width=150px, find the needed height, and zoom properly. See http://bl.ocks.org/hugolpz/9643738d5f79c7b594d0

enter image description here enter image description here enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...