An example of d3.behavior.zoom and d3.geo.path. By modifying the transform, the browser can rapidly redraw geographic features while panning and zooming, without the overhead of reprojection. This technique can be extended by combining with d3.geo.tile.
forked from mbostock's block: Zoomable Geography
xxxxxxxxxx
<meta charset="utf-8">
<style>
.overlay {
fill: none;
pointer-events: all;
}
.state {
fill: #aaa;
}
.county-border,
.state-border {
fill: none;
stroke: #fff;
stroke-linejoin: round;
stroke-linecap: round;
}
</style>
<body>
<h5 class="g-hed"></h5>
<p class="g-intro"></p>
<div class="g-chart"></div>
<div class="g-source"><span class="g-source-bold"></span><span class="g-source-reg"></span></div>
</body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
//Creates tooltip and makes it invisible
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var width = 960,
height = 500;
var path = d3.geo.path()
.projection(null);
var zoom = d3.behavior.zoom()
.translate([0, 0])
.scale(1)
.scaleExtent([1, 8])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var features = svg.append("g");
//Tells the nap what projection to use
var projection = d3.geo.albersUsa();
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.call(zoom);
//Moves selection to front
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
//Moves selection to back
d3.selection.prototype.moveToBack = function() {
return this.each(function() {
var firstChild = this.parentNode.firstChild;
if (firstChild) {
this.parentNode.insertBefore(this, firstChild);
}
});
};
/*
queue()
.defer(d3.json, "us.json")
.defer(d3.csv, "highrisk.csv")
.await(ready);
function ready(error, us, highrisk) {
if (error) throw error;
}
*/
d3.json("us.json", function(error, us) {
if (error) throw error;
features.append("path")
.datum(topojson.feature(us, us.objects.states))
.attr("class", "state")
.attr("d", path);
features.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "state-border")
.attr("d", path)
.style("stroke-width", "1.5px");
});
d3.csv("highrisk.csv", function(error, colleges) {
if (error) throw error;
features.selectAll("circle")
.data(colleges)
.enter()
.append("circle")
.attr("cx", function(d) {
return projection([d.lon, d.lat])[0];
})
.attr("cy", function(d) {
return projection([d.lon, d.lat])[1];
})
.attr("r", function(d) {
return d.moderate_risk*3 + d.high_risk*5;
})
.style("fill", function(d) {
if(d.moderate_risk == 1) {
return "#e17e41";
}
else {
return "#bc0019"
}
})
.style("stroke", "#4fbac4")
.style("stroke-width", 1)
.style("opacity", 0.75)
//Hovers
.on("mouseover", function(d) {
console.log(d.name);
var sel = d3.select(this);
sel.moveToFront();
d3.select(this).transition().duration(300).style("opacity", 0.8);
div.transition().duration(300)
.style("opacity", 1)
div.text(d.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY -30) + "px");
})
.on("mouseout", function() {
var sel = d3.select(this);
d3.select(this)
.transition().duration(300)
.style("opacity", 0.75);
div.transition().duration(300)
.style("opacity", 0);
})
});
function zoomed() {
features.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
features.select(".state-border").style("stroke-width", 1.5 / d3.event.scale + "px");
}
d3.select(self.frameElement).style("height", height + "px");
</script>
https://d3js.org/d3.v3.min.js
https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js
https://d3js.org/topojson.v1.min.js