function redraw() { var t = (0 | Math.log(projection.scale()) / Math.LN2) - 5 , e = d3.quadTiles(projection, t) , n = projection.clipExtent(); tiles_ = d3.quadTiles(projection.clipExtent([[1, 1], [width - 1, height - 1]]), t); var a = svg.selectAll(".tile").data(tiles_, key); a.enter().append("path").attr("class", "tile"), a.exit().remove(), a.attr("class", "tile").attr("d", path), svg.selectAll(".tile").data(e, key).classed("highlight", !0).exit().classed("highlight", !1); var r = svg.selectAll("text").data(e, key); r.enter().append("text").attr("text-anchor", "middle").text(key), r.exit().remove(), r.attr("transform", function (t) { return "translate(" + projection(t.centroid) + ")" }), projection.clipExtent(n) } function key(t) { return t.key.join(", ") } !function () { function t() { } function e(t) { return 360 * Math.atan(Math.exp(-t * Math.PI / 180)) / Math.PI - 90 } d3.quadTiles = function (n, a) { function r(t, n, p, d) { var h = p - t , g = e(n) , u = e(d) , v = l * h; i = !0, s.polygonStart(), s.lineStart(); for (var f = t; p + v / 2 > f && i; f += v) s.point(f, g); for (var m = g; (m += v) < u && i;) s.point(p, m); for (var f = p; f > t - v / 2 && i; f -= v) s.point(f, u); for (var m = u; (m -= v) > g && i;) s.point(t, m); if (i && s.point(t, g), s.lineEnd(), s.polygonEnd(), 360 / c >= h) i || o.push({ type: "Polygon", coordinates: [d3.range(t, p + v / 2, v).map(function (t) { return [t, n] }).concat([[p, .5 * (n + d)]]).concat(d3.range(p, t - v / 2, -v).map(function (t) { return [t, d] })).concat([[t, .5 * (n + d)]]).concat([[t, n]]).map(function (t) { return [t[0], e(t[1])] })], key: [0 | (180 + t) / 360 * c, 0 | (180 + n) / 360 * c, a], centroid: [.5 * (t + p), .5 * (g + u)] }); else if (!i) { var f = .5 * (t + p) , m = .5 * (n + d); r(t, n, f, m), r(f, n, p, m), r(t, m, f, d), r(f, m, p, d) } } var i, o = [], c = 1 << (a = Math.max(0, a)), l = Math.max(.2, Math.min(1, .01 * a)), p = n.precision(), s = n.precision(960).stream({ point: function () { i = !1 }, lineStart: t, lineEnd: t, polygonStart: t, polygonEnd: t }); return r(-180, -180, 180, 180), n.precision(p), o } }(); var width = 960 , height = 600 , p = 100 , projection = d3.geo.albers().rotate([0, 0]).center([0, 38.7]).scale(1280).translate([width / 2, height / 2]).precision(.1).clipExtent([[p, p], [width - p, height - p]]) , path = d3.geo.path().projection(projection) , svg = d3.select("#map").append("svg").attr("width", width).attr("height", height).style("pointer-events", "all").call(d3.behavior.zoom().translate(projection.translate()).scale(projection.scale()).scaleExtent([50, 1e7]).on("zoom", function () { projection.scale(d3.event.scale).translate(d3.event.translate), redraw() })); svg.append("path").datum({ type: "Sphere" }).attr("class", "outline").attr("d", path), redraw();