A variant of the Zoom to Bounding Box example that uses zoom transitions to smoothly interpolate between different views. This example also allows you to freely pan and zoom with the mouse (or touch).
forked from mbostock's block: Zoom to Bounding Box II
forked from Fil's block: Zoom to Bounding Box II d3v4
xxxxxxxxxx
<meta charset="utf-8">
<style>
.background {
fill: none;
pointer-events: all;
}
.feature {
fill: #ccc;
cursor: pointer;
}
.feature.active {
fill: orange;
}
.mesh {
fill: none;
stroke: #fff;
stroke-linecap: round;
stroke-linejoin: round;
}
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>
var width = 960,
height = 500,
active = d3.select(null);
var projection = d3.geoAlbersUsa()
.scale(1000)
.translate([width / 2, height / 2]);
var zoom = d3.zoom()
.on("zoom", zoomed);
var path = d3.geoPath()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.on("click", stopped, true);
var bg = svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
var country;
svg
.call(zoom) // delete this line to disable free zooming
d3.json("https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/us.json", function(error, us) {
if (error) throw error;
country = topojson.feature(us, us.objects.states)
g.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.attr("class", "feature")
.on("click", clicked);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "mesh")
.attr("d", path);
bg.dispatch('click')
});
function clicked(d) {
active.classed("active", false);
if (active.node() === this || this.getAttribute('class') !== 'feature') {
d = country
active = d3.select(null);
}else{
active = d3.select(this).classed("active", true);
}
zoomToBounds(d)
}
function zoomToBounds(geoObject) {
var bounds = path.bounds(geoObject),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2,
scale = Math.max(1, Math.min(8, 0.9 / Math.max(dx / width, dy / height))),
translate = [width / 2 - scale * x, height / 2 - scale * y];
let transform = d3.zoomIdentity
.translate(translate[0], translate[1])
.scale(scale);
svg.transition()
.duration(750)
.call(zoom.transform, transform);
}
function zoomed() {
var transform = d3.event.transform;
g.style("stroke-width", 1.5 / transform.k + "px");
g.attr("transform", transform);
}
// If the drag behavior prevents the default click,
// also stop propagation so we don’t click-to-zoom.
function stopped() {
if (d3.event.defaultPrevented) d3.event.stopPropagation();
}
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-93898246-1', 'auto');
ga('send', 'pageview');
</script>
</body>
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v2.min.js