block by fil 7db0a78e042c5bfaa807f44bd6c58aa2

Translucent Earth

Full Screen

Also at https://beta.observablehq.com/@fil/translucent-earth

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://unpkg.com/d3@4"></script>
<script src="https://unpkg.com/topojson"></script>
<script src="https://unpkg.com/d3-inertia"></script>
<script src="https://unpkg.com/versor"></script>
<script>

var width = 960,
    height = 500;

var velocity = .01;

var projection = d3.geoOrthographic()
.rotate([-10,-30]);
  
var canvas = d3.select("body").append("canvas")
    .attr("width", width)
    .attr("height", height);

var context = canvas.node().getContext("2d");

    // retina display
var devicePixelRatio = window.devicePixelRatio || 1;
  canvas.style('width', canvas.attr('width')+'px');
  canvas.style('height', canvas.attr('height')+'px');
  canvas.attr('width', canvas.attr('width') * devicePixelRatio);
  canvas.attr('height', canvas.attr('height') * devicePixelRatio);
  context.scale(devicePixelRatio,devicePixelRatio);

var path = d3.geoPath()
    .projection(projection)
    .context(context);

  
var backprojection = d3.geoProjection(function(a,b) {
  return d3.geoOrthographicRaw(-a,b);
})
  .clipAngle(90)
  .translate(projection.translate())
  .scale(projection.scale());

var backpath = d3.geoPath()
    .projection(backprojection)
    .context(context);


d3.json("https://unpkg.com/world-atlas/world/110m.json", function(error, world) {
  if (error) throw error;

  var land = topojson.feature(world, world.objects.land);

  d3.timer(function(elapsed) {
    var rotate = projection.rotate();
    rotate[0] += velocity * 20;
    projection.rotate(rotate);
    render();
  });
    
function render() {
  var rotate = projection.rotate();
    backprojection.rotate([rotate[0] + 180, -rotate[1], -rotate[2]]);

    context.clearRect(0, 0, width, height);

    context.beginPath();
    path({type:"Sphere"});
    context.fillStyle = '#fcfcfc';
    context.fill();

    context.beginPath();
    backpath(land);
    context.fillStyle = '#d0ddfa';
    context.fill();
    context.beginPath();
    backpath(d3.geoGraticule()());
    context.lineWidth = .1;
    context.strokeStyle = '#97b3f6';
    context.stroke();
    

    context.beginPath();
    path(d3.geoGraticule()());
    context.lineWidth = .1;
    context.strokeStyle = '#1046c6';
    context.stroke();

    context.beginPath();
    path(land);
    context.lineWidth = 1;
    context.strokeStyle = '#1046c6';
    context.stroke();
    context.fillStyle = '#5c88ee';
    var alpha = context.globalAlpha;
    context.globalAlpha = 1;
    context.fill();
    context.globalAlpha = alpha;

    context.beginPath();
    path({type: "Sphere"});
    context.lineWidth = .1;
    context.strokeStyle = '#1046c6';
    context.stroke();

}

  d3.geoInertiaDrag(canvas, render);
  canvas.style('cursor', 'move')


});
</script>