Conic Conformal instead of orthographic.
xxxxxxxxxx
<meta charset='utf-8'>
<style>
body{ background: #000; }
</style>
<body>
<canvas></canvas>
</body>
<script src='d3.v4.min.js'></script>
<script src="topojson.js"></script>
<script>
var ƒ = d3.f
var width = 960
var height = 500
var canvas = d3.select('canvas')
.at({width: width, height: height})
.node()
var ctx = canvas.getContext('2d')
var projection = d3.geoConicConformal().scale(300)
var path = d3.geoPath().projection(projection).context(ctx)
d3.queue()
.defer(d3.json, 'world.json')
.await(function(err, world) {
var land = topojson.feature(world, world.objects.world)
var countries = topojson.feature(world, world.objects.world).features
.filter(function(d){ return d3.geoArea(d) > .0001 })
!(function transition(){
ctx.fillStyle = "#0f0";
ctx.strokeStyle = "#fff";
d3.transition().duration(0).delay(300)
.tween('rotate', function(){
var country = countries[Math.random()*countries.length >> 0 ]
// var country = countries.filter(function(d){ return d.name == 'Mexico' })[0]
var p = d3.geoCentroid(country)
var bb = d3.geoBounds(country)
var p0 = (bb[0][1]*2 + bb[1][1]*1)/3
var p1 = (bb[0][1]*1 + bb[1][1]*2)/3
projection
.rotate([-p[0], -p[1]])
.parallels([p0, p1])
ctx.clearRect(0, 0, width, height)
// ctx.beginPath(), path(land), ctx.stroke()
ctx.beginPath(), path(country), ctx.fill()
return function(t){}
})
.on('end', transition)
})()
})
</script>