This example uses d3.behavior.zoom with a canvas transform and pre-projected geometry for map panning and zooming. This approach is faster than reprojecting, but still slower than an SVG transform. A faster variation of this approach is to use dynamic simplification and viewport clipping.
Last active
February 9, 2016 01:53
-
-
Save mbostock/09dd5ad7d6bfd40187e0 to your computer and use it in GitHub Desktop.
Map Pan & Zoom III
This file contains hidden or 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 hidden or 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
.DS_Store | |
build | |
node_modules |
This file contains hidden or 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"> | |
<style> | |
canvas { | |
background: #eee; | |
} | |
</style> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script src="//d3js.org/topojson.v1.min.js"></script> | |
<body> | |
<script> | |
var width = 960, | |
height = 960; | |
var zoom = d3.behavior.zoom() | |
.translate([0, 0]) | |
.scale(1) | |
.scaleExtent([1, 8]); | |
var canvas = d3.select("body").append("canvas") | |
.attr("width", width) | |
.attr("height", height); | |
var context = canvas.node().getContext("2d"); | |
context.lineJoin = "round"; | |
context.lineCap = "round"; | |
context.strokeStyle = "#fff"; | |
var path = d3.geo.path() | |
.projection(null) | |
.context(context); | |
d3.json("world.json", function(error, world) { | |
if (error) throw error; | |
var sphere = topojson.feature(world, world.objects.sphere), | |
land = topojson.feature(world, world.objects.land), | |
boundary = topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }); | |
canvas | |
.call(zoom.on("zoom", zoomed)) | |
.call(zoom.event); | |
function zoomed() { | |
var t = zoom.translate(), | |
s = zoom.scale(); | |
context.clearRect(0, 0, width, height); | |
context.save(); | |
context.translate(t[0], t[1]); | |
context.scale(s, s); | |
context.lineWidth = 1 / s; | |
context.beginPath(); | |
path(sphere); | |
context.fillStyle = "#fff"; | |
context.fill(); | |
context.beginPath(); | |
path(land); | |
context.fillStyle = "#000"; | |
context.fill(); | |
context.beginPath(); | |
path(boundary); | |
context.stroke(); | |
context.restore(); | |
} | |
}); | |
d3.select(self.frameElement).style("height", height + "px"); | |
</script> |
This file contains hidden or 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
GENERATED_FILES = \ | |
world.json | |
all: $(GENERATED_FILES) | |
clean: | |
rm -rf -- %(GENERATED_FILES) | |
.PHONY: all clean | |
build/ne_50m_admin_0_countries.zip: | |
mkdir -p $(dir $@) | |
curl -o $@ 'http://www.nacis.org/naturalearth/50m/cultural/$(notdir $@)' | |
build/ne_50m_admin_0_countries.shp: build/ne_50m_admin_0_countries.zip | |
unzip -d $(dir $@) $< | |
touch $@ | |
world.json: build/ne_50m_admin_0_countries.shp sphere.json | |
node_modules/.bin/topojson \ | |
-q 1e5 \ | |
--projection='width = 960, height = 960, d3.geo.mercator() \ | |
.translate([width / 2, height / 2]) \ | |
.scale((width - 1) / 2 / Math.PI)' \ | |
-- \ | |
countries=build/ne_50m_admin_0_countries.shp \ | |
sphere=sphere.json | \ | |
node_modules/.bin/topojson-merge \ | |
-o $@ \ | |
--io=countries \ | |
--oo=land |
This file contains hidden or 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
{ | |
"name": "anonymous", | |
"version": "0.0.1", | |
"private": true, | |
"dependencies": { | |
"topojson": "1" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Quick question: what is that sphere.json Makefile target? I'm trying to adapt this to work with the 10m map and it seems to be missing.
Also the URL for the naturalearth data is 404ing. Looks like this works though: http://naciscdn.org/naturalearth/50m/cultural/ne_50m_admin_0_countries.zip
Thanks!