A combination of Mike Bostock’s Atlantis projection and Jason Davies’ Automatically Colored World Map
<!DOCTYPE html>
<meta charset="utf-8">
<style>
html, body {
background: #f3f3f3;
}
.country {
fill: #ccc;
stroke: #fff;
stroke-width: .5px;
stroke-linejoin: round;
}
.graticule {
fill: none;
stroke: #000;
stroke-opacity: .5;
stroke-width: .5px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="//d3js.org/topojson.v0.min.js"></script>
<script>
var width = 960,
height = 880;
var projection = d3.geo.mollweide()
.rotate([30, -45, 90])
.scale(150)
.translate([width * .46, height / 2])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule()
.step([10, 10])
.extent([[-180, -80], [180, 80 + 1e-3]]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "rotate(90 480,480)");
svg.append("g")
.attr("class", "graticule")
.selectAll("path")
.data(graticule.lines)
.enter().append("path")
.attr("d", path);
d3.json("readme-world.json", function(error, world) {
var neighbors = topojson.neighbors(world, world.objects.countries.geometries),
colors = d3.scale.category10().range().map(function(c) { c = d3.hcl(c); c.c *= .8; c.h = c.h*0.9 + 100; c.l = 60; return c; }),
nColors = colors.length,
colorByObject = {};
world.objects.countries.geometries.forEach(function(o, index) {
var oNeighbours = neighbors[index] || [],
m = oNeighbours.length;
nextColor:
for (var i = 0; i < nColors; ++i) {
var color = colors[i];
for (var j = 0; j < m; ++j) {
if (colorByObject[oNeighbours[j].id] === color) continue nextColor;
}
colorByObject[o.id] = color;
break;
}
});
svg.selectAll(".country")
.data(topojson.object(world, world.objects.countries).geometries)
.enter().insert("path", ".graticule")
.attr("class", "country")
.attr("d", path)
.style("fill", function(d) { return colorByObject[d.id]; });
});
topojson.neighbors = function(topology, objects) {
var objectsByArc = topology.arcs.map(function() { return []; });
function line(arcs, index) {
for (var i = 0, n = arcs.length, arc; i < n; ++i) {
if ((arc = arcs[i]) < 0) arc = ~arc;
objectsByArc[arc].push(index);
}
}
function polygon(arcs, i) {
arcs.forEach(function(arc) { line(arc, i); });
}
function geometry(o, i) {
geometryType[o.type](o.arcs, i);
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
};
objects.forEach(geometry);
var neighbors = [];
objectsByArc.forEach(function(d) {
if (d.length < 2) return;
if (!neighbors[d[0]]) neighbors[d[0]] = [];
if (!neighbors[d[1]]) neighbors[d[1]] = [];
neighbors[d[0]].push(objects[d[1]]);
neighbors[d[1]].push(objects[d[0]]);
});
return neighbors;
};
d3.select(self.frameElement).style("height", height + "px");
</script>