A variation of the dynamic simplification demonstration using a filled polygon rather than a stroked mesh. As a result, the effect of simplification is almost imperceptible during zooming. Aside from the fluid framerate achieved by faster rendering, of course!
Last active
February 9, 2016 02:02
-
-
Save mbostock/6287633 to your computer and use it in GitHub Desktop.
Dynamic Simplification III
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<body> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script src="//d3js.org/topojson.v1.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500; | |
var chesapeake = [-75.959, 38.250]; | |
var scale, | |
translate, | |
area; // minimum area threshold for simplification | |
var clip = d3.geo.clipExtent() | |
.extent([[0, 0], [width, height]]); | |
var simplify = d3.geo.transform({ | |
point: function(x, y, z) { | |
if (z >= area) this.stream.point(x * scale + translate[0], y * scale + translate[1]); | |
} | |
}); | |
var zoom = d3.behavior.zoom() | |
.size([width, height]) | |
.on("zoom", zoomed); | |
// This projection is baked into the TopoJSON file, | |
// but is used here to compute the desired zoom translate. | |
var projection = d3.geo.mercator() | |
.translate([0, 0]) | |
.scale(4000) | |
.precision(0); | |
var canvas = d3.select("body").append("canvas") | |
.attr("width", width) | |
.attr("height", height); | |
var context = canvas.node().getContext("2d"); | |
var path = d3.geo.path() | |
.projection({stream: function(s) { return simplify.stream(clip.stream(s)); }}) | |
.context(context); | |
d3.json("us.json", function(error, json) { | |
if (error) throw error; | |
canvas | |
.datum(topojson.feature(topojson.presimplify(json), json.objects.land)) | |
.call(zoomTo(chesapeake, 0.05).event) | |
.transition() | |
.duration(5000) | |
.each(jump); | |
}); | |
function zoomTo(location, scale) { | |
var point = projection(location); | |
return zoom | |
.translate([width / 2 - point[0] * scale, height / 2 - point[1] * scale]) | |
.scale(scale); | |
} | |
function zoomed(d) { | |
translate = zoom.translate(); | |
scale = zoom.scale(); | |
area = 1 / scale / scale; | |
context.clearRect(0, 0, width, height); | |
context.beginPath(); | |
path(d); | |
context.fill(); | |
} | |
function jump() { | |
var t = d3.select(this); | |
(function repeat() { | |
t = t.transition() | |
.call(zoomTo(chesapeake, 1.25).event) | |
.transition() | |
.call(zoomTo(chesapeake, 0.05).event) | |
.each("end", repeat); | |
})(); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment