block by milroc e90cfd6698f9ed318a2c

States & Provinces (warning may cause seizures)

Full Screen

Quick demo of getting regions into a world map. Not performant.

WARNING: Interaction may cause seizures

index.html

<!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 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; }),
      provinces = topojson.feature(world, world.objects.provinces);

  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 = "#f00";
    context.stroke();

    provinces.features.forEach(function(province) {
      context.beginPath();
      path(province);
      context.fillStyle = d3.rgb(Math.random() * 255, Math.random() * 255, Math.random() * 255).toString();
      context.fill();
    })

    context.restore();
  }
});

d3.select(self.frameElement).style("height", height + "px");

</script>

Makefile

GENERATED_FILES = \
	world.json

all: $(GENERATED_FILES)

clean:
	rm -rf -- %(GENERATED_FILES)

.PHONY: all clean
build/ne_10m_admin_0_countries.zip:
	mkdir -p $(dir $@)
	curl -o $@ 'http://www.naturalearthdata.com/download/10m/cultural/$(notdir $@)'

build/ne_10m_admin_0_countries.shp: build/ne_10m_admin_0_countries.zip
	unzip -d $(dir $@) $<
	touch $@

build/ne_10m_admin_1_states_provinces.zip:
	mkdir -p $(dir $@)
	curl -o $@ 'http://www.naturalearthdata.com/download/10m/cultural/$(notdir $@)'

build/ne_10m_admin_1_states_provinces.shp: build/ne_10m_admin_1_states_provinces.zip
	unzip -d $(dir $@) $<
	touch $@

world.json: build/ne_10m_admin_1_states_provinces.shp build/ne_10m_admin_0_countries.shp sphere.json
	node_modules/.bin/topojson \
		-p gn_a1_code -q 1e5 --simplify-proportion 0.1 \
		--projection='width = 960, height = 960, d3.geo.mercator() \
				.translate([width / 2, height / 2]) \
				.scale((width - 1) / 2 / Math.PI)' \
		-- \
		provinces=build/ne_10m_admin_1_states_provinces.shp \
		countries=build/ne_10m_admin_0_countries.shp \
		sphere=sphere.json | \
			node_modules/.bin/topojson-merge \
				--io countries \
				--oo land \
				-o $@

package.json

{
  "name": "anonymous",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "topojson": "1"
  }
}

sphere.json

{
  "type": "Sphere"
}