Skip to content

Instantly share code, notes, and snippets.

@sfinktah
Forked from mbostock/.block
Last active October 5, 2015 11:14
Show Gist options
  • Save sfinktah/5987ecbfb3c04c49d122 to your computer and use it in GitHub Desktop.
Save sfinktah/5987ecbfb3c04c49d122 to your computer and use it in GitHub Desktop.
Map Pan & Zoom IV
.DS_Store
build
node_modules

This example uses d3.behavior.zoom with pre-projected geometry for map panning and zooming, in conjunction with dynamic simplification and viewport clipping. This approach is quite fast, but more work to implement than an SVG transform.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
canvas {
background: #eee;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<body>
<script>
var width = 960,
height = 960;
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()
.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";
var path = d3.geo.path()
.projection({stream: function(s) { return simplify.stream(clip.stream(s)); }})
.context(context);
d3.json("world.json", function(error, world) {
if (error) throw error;
topojson.presimplify(world);
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() {
translate = zoom.translate();
scale = zoom.scale();
area = 1 / scale / scale;
context.clearRect(0, 0, width, height);
context.save();
context.beginPath();
path(sphere);
context.fillStyle = "#fff";
context.fill();
context.beginPath();
path(land);
context.fillStyle = "#000";
context.fill();
context.beginPath();
path(boundary);
context.strokeStyle = "#fff";
context.stroke();
context.restore();
}
});
d3.select(self.frameElement).style("height", height + "px");
</script>
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 \
--io countries \
--oo land \
-o $@
{
"name": "anonymous",
"version": "0.0.1",
"private": true,
"dependencies": {
"topojson": "1"
}
}
{
"type": "Sphere"
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment