|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
|
|
<body> |
|
<div id="map"></div> |
|
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<script src="//d3js.org/d3.geo.projection.v0.min.js" charset="utf-8"></script> |
|
<script src="//d3js.org/topojson.v1.min.js"></script> |
|
<script src="//d3js.org/queue.v1.min.js"></script> |
|
|
|
<style> |
|
|
|
body { |
|
background: #fcfcfa; |
|
} |
|
|
|
.stroke { |
|
fill: none; |
|
stroke: #000; |
|
stroke-width: 3px; |
|
} |
|
|
|
.fill { |
|
fill: #d6fefa; |
|
} |
|
|
|
.graticule { |
|
fill: none; |
|
stroke: #777; |
|
stroke-width: .5px; |
|
stroke-opacity: .5; |
|
} |
|
|
|
.land { |
|
fill: #000; |
|
} |
|
|
|
.image.country { |
|
stroke: #000; |
|
stroke-width: 0.5px; |
|
} |
|
|
|
.boundary { |
|
fill: none; |
|
stroke: #000; |
|
stroke-width: 0.5px; |
|
} |
|
|
|
</style> |
|
<script> |
|
var wflags = "https://gist.githubusercontent.com/espinielli/5107491/raw/world-country-flags.tsv", |
|
w110 = "https://gist.githubusercontent.com/mbostock/4090846/raw/world-110m.json", |
|
wnames = "https://gist.githubusercontent.com/mbostock/4090846/raw/world-country-names.tsv"; |
|
|
|
|
|
var width = 1200, |
|
height = 700; |
|
|
|
// |
|
var projection = d3.geo.robinson() |
|
.scale(180) |
|
.translate([width / 2, height / 2]) |
|
.precision(.1); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var graticule = d3.geo.graticule(); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var defs = svg.append("defs"); |
|
|
|
defs.append("path") |
|
.datum({type: "Sphere"}) |
|
.attr("id", "sphere") |
|
.attr("d", path); |
|
|
|
svg.append("use") |
|
.attr("class", "stroke") |
|
.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); |
|
|
|
var q = queue() |
|
.defer(d3.json, w110) |
|
.defer(d3.tsv, wnames) |
|
.defer(d3.tsv, wflags) |
|
.await(ready); |
|
|
|
|
|
function ready(error, world, names, flags) { |
|
if (error) { |
|
alert('error: ' + error); |
|
return; |
|
} |
|
|
|
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 countries = topojson.feature(world, world.objects.countries).features, |
|
land = topojson.feature(world, world.objects.land); |
|
|
|
countries = countries.filter(function(d) { |
|
return names.some(function(n) { |
|
if (d.id == n.id) { |
|
return d.name = n.name; |
|
} |
|
}); |
|
}); |
|
|
|
countries = countries.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(countries) |
|
.enter() |
|
.append("clipPath") |
|
.attr("class", "mask") |
|
.attr("id", function(d) {return "iso-" + d.id}) |
|
.append("path") |
|
.attr("d", path); |
|
|
|
|
|
svg.selectAll("country") |
|
.data(countries) |
|
.enter() |
|
.insert("image", ".graticule") |
|
.attr("class", "country") |
|
.attr("xlink:href", function (d){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 + ")"; |
|
}); |
|
|
|
// interior boundaries |
|
svg.insert("path", ".graticule") |
|
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; })) |
|
.attr("class", "boundary") |
|
.attr("clip-path", "url(#sphere)") |
|
.attr("d", path); |
|
// exterior boundaries |
|
svg.insert("path", ".graticule") |
|
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a === b})) |
|
.attr("d", path) |
|
.attr("class", "boundary"); |
|
} |
|
|
|
|
|
|
|
|
|
</script> |
|
</body> |
|
|
|
</html> |