Victorian fox looking at a computer.
Jack of all trad.es

a work in progress - dev & misc

Using a Globe to Visualize Geographic Data on the Web

globe.gl by Vasco Asturiano is an open source tool that allows developers to display a globe on a web page. It's really cool. After stumbling upon the already-heavily starred project the other day, I thought this might be a fun way to spend a few hours this weekend.

The best thing about globe.gl is that it's fun. Only a little bit of set up and you have the world as your fingertips.

import Globe from "globe.gl";

function renderGlobeOne() {
  const container = document.getElementById("globe-1");

  if (!container) {
    return;
  }

  const globe = Globe();

  globe
    .globeImageUrl("//unpkg.com/three-globe/example/img/earth-blue-marble.jpg")
    .width(container.getBoundingClientRect().width)
    .height(container.getBoundingClientRect().height)
    .backgroundColor("#ffffff");

  globe(container);
}

renderGlobeOne();

The globe object is a builder (that calls itself to start building/rendering the visualization). Under the hood this is using three.js to render everything into a <canvas> a couple levels deeper in the DOM from our container. We get this:

An interactive globe! Pretty swish.

Web performance

A quick aside, while super fun, the globe.gl (and thus also three.js) is absolutely massive. Including this single import alone and the couple lines of code above took the size of this script to 1.7MB - way, way more than you should have for most use cases.

Visualizing a flight path

A strength of globe.gl is its layering, which allows you to add different elements to the globe. Supposing I want to visualize the next plane trip I'll be taking, I can add an arc to the map. I dug up some coordinates for SEATAC airport and Heathrow. Side note, there's a great example of visualizing airline routes in the globe.gl repo.

Assigning location related data

I'm going to start by creating a few constants that I can refer to when building up the globe's configuration. The departure port, the arrival port, the ideal starting position to visualize both spots on the globe without any need for scrolling or rotating the globe.

const CAMERA = { lat: 56, lng: -82, altitude: 2 };
const SEATAC = { lat: 47, lng: -122.6, altitude: 0.4 };
const HEATHROW = { lat: 51.47002, lng: -0.454295, altitude: 0.4 };
const SEATAC_TO_HEATHROW_ARC = {
  startLat: SEATAC.lat,
  startLng: SEATAC.lng,
  endLat: HEATHROW.lat,
  endLng: HEATHROW.lng,
  color: ["#84ffc9", "#aab2ff", "#eca0ff"],
};

As you can see the above assigns some GPS coordiates and altitude values, the puts them an "easy" to reference object that will represent the basic information about our arc.

Further configuring the globe

The following steps could be written all in one long chain of calls to the globe object. I've just separated them out to make explaining each of them a little clearer.

  1. Assign the an image to wrap around the globe. I found this URL in the examples section of the globe.gl repo.
    globe.globeImageUrl("//unpkg.com/three-globe/example/img/earth-night.jpg");
  2. Change the default starting view of the globe to the coordinates from our CAMERA constant.
    globe.pointOfView(CAMERA, 1000);
  3. Set the width and height of the globe to the width and height of the containing html element.
    globe.width(container.getBoundingClientRect().width);
    globe.height(container.getBoundingClientRect().height);

The several steps above were precursors to adding the arc. Let's move on to that.

Showing the arc

Arcs have a number of configurable values and so you'll have to refer to the docs to get them all. Here are a few basic configurations that I chose to make.

globe
  .arcsData([SEATAC_TO_HEATHROW_ARC]) // 1
  .arcColor("color") // 2
  .arcStroke(0.5) // 3
  .arcDashLength(1) // 4
  .arcDashGap(1) // 5
  .arcDashAnimateTime(5000); // 6

globe(container); // 7
  1. Add our arc GPS, altitude, and color data to the arcs layer of the globe. This is an array, but I'm only visualizing one flight, so I'll pass in one item only.
  2. Call arcColor with a string to indicate the property on the arc array items to check to get color data. This is an accessor. I've passed color here to indicate the globe should look in the color property5. of SEATAC_TO_HEATHROW_ARC (or any other item in that array).
  3. Use arcStroke to make the arc bigger.
  4. Set arcDashLength to 1, the length of the arc should be the entire length between Seattle and London.
  5. Similar to #4, configure the length of space between arcs. Setting this to 1 means a new arc will appear as soon as the previously rendered arc disappears.
  6. Set the length of time in milliseconds it should take a single arc to animate.
  7. Render the globe.

This configuration results in:

That's all for today folks!

I've spent enough time dabbling here. Check out globe.gl for yourself. It's very fun to play with, but I have the feeling I've barely scatched the surface of globe.gl's API. There are still over a dozen other layers to try out!

Consider spending an hour (at least!) spelunking through the examples in the repo.

p.s. GeoJSON files are interesting!

Really just JSON, GeoJSON is a file format used to encode geographic data. There is a lot of data out there, so the visualization ideas are nearly endless. I dug up the following during a quick information-gathering effort.

p.s. This is the markup I used for my containers

<div
  id="globe-N"
  style="
    width: 100%;
    aspect-ratio: 1 / 1;
    border: 1px solid grey;
    border-radius: 24px;
    overflow: hidden;
    margin-block-start: 24px;"
></div>