var width = 960, height = 500, centered; var projection = d3.geo.albersUsa() .scale(width) .translate([width / 2, height / 2]); var path = d3.geo.path() .projection(projection); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var graticule = d3.geo.graticule(); var defs = svg.append("defs"); defs.append("path") .datum({type: "Sphere"}) .attr("id", "sphere") .attr("d", path); svg.append("use") .attr("class", "stroke-sphere") .attr("xlink:href", "#sphere"); svg.append("use") .attr("class", "fill") .attr("xlink:href", "#sphere"); svg.append("path") .datum(graticule) .attr("class", "graticule") .attr("d", path); queue() .defer(d3.json, "https://gist.githubusercontent.com/mbostock/4090846/raw/us.json") .defer(d3.tsv, "us-state-names-plus.tsv") .defer(d3.tsv, "us-state-id-flag-urls.tsv") .await(ready); function ready(error, usa, names, flags) { var dims = []; flags.forEach(function (d) { d.id = +d.id;}); flags.sort(function(a,b) { return +a.id < +b.id ? -1 : +a.id > +b.id ? +1 : 0; }); var states = topojson.feature(usa, usa.objects.states).features; states = states.filter(function(d) { return names.some(function(n) { if (d.id == n.id) { return d.name = n.name; } }); }); states = states.filter(function(d) { return flags.some(function(n) { if (d.id == n.id) { var bounds = path.bounds(d); if (bounds[0][0] < 0) bounds[0][0] = 0; if (bounds[1][0] > width) bounds[1][0] = width; if (bounds[0][1] < 0) bounds[0][1] = 0; if (bounds[1][1] < 0) bounds[1][1] = height; d.bounds = bounds; return d.url = n.url; } }); }); defs.selectAll("mask") .data(states) .enter() .append("clipPath") .attr("class", "mask") .attr("id", function(d) {return "iso-" + d.id}) .append("path") .attr("d", path); svg.selectAll("state") .data(states) .enter() .insert("image", ".graticule") .attr("class", "state") .attr("xlink:href", function (d){console.log(d.url);return d.url;}) .attr("x", function (d) {return d.bounds[0][0];}) .attr("y", function (d) {return d.bounds[0][1];}) .attr("width", function (d) {return d.bounds[1][0] - d.bounds[0][0];}) .attr("height", function (d) {return d.bounds[1][1] - d.bounds[0][1];}) .attr("preserveAspectRatio", "none") .attr("clip-path", function(d) { return "url(#iso-" + d.id + ")"; }); defs.selectAll("path") .data(states) .enter().append("path") .attr("d", path) .attr("id", function(d) { var b = path.bounds(d), s, m, t; s = [(b[1][0] - b[0][0]), (b[1][1] - b[0][1])]; m = Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height); t = [(width - m * (b[1][0] + b[0][0])) / 2, (height - m * (b[1][1] + b[0][1])) / 2]; dims[d.id] = {"extent": s, "translate": t}; return "p"+d.id; }); svg.insert("path", ".graticule") .datum(topojson.mesh(usa, usa.objects.states, function(a, b) { return a !== b; })) .attr("class", "boundary") .attr("d", path); // exterior boundaries svg.insert("path", ".graticule") .datum(topojson.mesh(usa, usa.objects.states, function(a, b) { return a === b})) .attr("d", path) .attr("class", "boundary"); };