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:
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