<!DOCTYPE html> <meta charset="utf-8"> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <script src="http://d3js.org/topojson.v1.min.js"></script> <script> var width = 960, height = 500; // Returns UTM zome from longitude var utmZone = d3.scale.linear() .domain([-177, 177]) .rangeRound([1, 60]) .clamp(true); var projection = d3.geo.transverseMercator() .translate([width / 2, height / 2]) .scale(165) .clipAngle(90); var graticule = d3.geo.graticule() .step([6, 8]); 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(projection) .context(context); d3.json("/mbostock/raw/4090846/world-110m.json", function(error, world) { var land = topojson.feature(world, world.objects.land), center = -180, velocity = .015, zone, zoneText, zoneStart, zoneEnd, t0; d3.timer(function() { context.clearRect(0, 0, width, height); projection.rotate([-center, 0]); zone = utmZone(center); zoneText = (1e15 + zone + "").slice(-2), // Add leading zero zoneStart = -186 + zone * 6; zoneEnd = zoneStart + 6; t0 = Date.now(); render(); center += velocity * (Date.now() - t0); if (center >= 180) { // New roundtrip center = -180; } }); function render() { context.beginPath(); path(land); context.fillStyle = 'black'; context.fill(); context.beginPath(); path({ "type": "Polygon", "coordinates": [[[zoneStart, 84], [zoneEnd, 84], [zoneEnd, -80], [zoneStart, -80], [zoneStart, 84]]] }); context.fillStyle = "rgba(255, 255, 0, .5)"; context.fill(); context.beginPath(); path(graticule()); context.lineWidth = .5; context.stroke(); context.beginPath(); context.fillStyle = "#eee"; context.strokeStyle = "black"; context.lineWidth = 1; context.font = "bold 40px Verdana"; context.fillText(zoneText, width / 2 - 30, height / 2); context.strokeText(zoneText, width / 2 - 30, height / 2); } }); </script>