block by fil 02e6d4c63ab52d202ca9d922b4b9000f

Floating Landmasses in d3v4

Full Screen

By changing the scale and clip angle of an orthographic projection, this example creates two concentric spheres to give the appearance of floating landmasses. Inspired by Derek Watkin’s Faux-3D Arcs.

forked from mbostock‘s block: Floating Landmasses

Now also using d3-inertia.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  background: #fcfcfa;
}

canvas {
  position: absolute;
  top: 0;
  left: 0;
  cursor: move;
  cursor: drag;
}

.blur {
  -webkit-filter: blur(6px);
  filter: blur(6px);
}

</style>
<body>
<script src="https://unpkg.com/d3"></script>
<script src="https://unpkg.com/topojson"></script>
<script src="https://unpkg.com/versor"></script>
<script src="https://unpkg.com/d3-inertia"></script>
<script>

var width = 960,
    height = 960,
    speed = -1e-2,
    start = Date.now();

var sphere = {type: "Sphere"};

var projection = d3.geoOrthographic()
    .translate([width / 2, height / 2])
    .precision(.5)
.rotate([-70, -25]);

var graticule = d3.geoGraticule();

var canvas1 = d3.select("body").append("canvas"),
    canvas2 = d3.select("body").append("canvas").attr("class", "blur"),
    canvas3 = d3.select("body").append("canvas");

d3.selectAll("canvas")
    .attr("width", width)
    .attr("height", height);

var context1 = canvas1.node().getContext("2d"),
    context2 = canvas2.node().getContext("2d"),
    context3 = canvas3.node().getContext("2d");

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

projection.scale(width / 2.3).clipAngle(90);

context1.beginPath();
path.context(context1)(sphere);
context1.lineWidth = 3;
context1.strokeStyle = "#000";
context1.stroke();

context1.beginPath();
path(sphere);
context1.fillStyle = "#fff";
context1.fill();

context2.fillStyle = "rgba(0,0,0,.4)";
context3.strokeStyle = "rgba(0,0,0,.2)";

var render = function(){};

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

  var land = topojson.feature(topo, topo.objects.land),
      grid = graticule();

  render = function() {
    context2.clearRect(0, 0, width, height);
    context3.clearRect(0, 0, width, height);

    projection.scale(width / 2.3).clipAngle(90);

    context2.beginPath();
    path.context(context2)(land);
    context2.fill();

    context3.beginPath();
    path.context(context3)(grid);
    context3.lineWidth = .5;
    context3.stroke();

    projection.scale(width / 2.2).clipAngle(106.3);

    context3.beginPath();
    path(land);
    context3.fillStyle = "#737368";
    context3.fill();

    projection.scale(width / 2.2).clipAngle(90);

    context3.beginPath();
    path(land);
    context3.fillStyle = "#dadac4";
    context3.fill();
  };
  
  render();
});

  var inertia = d3.geoInertiaDrag(canvas3, draw);

  d3.timer(function(e){
    if (inertia.timer) return;
    var rotate = projection.rotate();
    projection.rotate([rotate[0] + 0.1, rotate[1], rotate[2]]);
    draw();
  })
  
d3.select(self.frameElement).style("height", height + "px");

</script>