How to Build a WorldWind Web App

Lesson 2: WorldWind Globe

In a hurry? Here’s the completed code: Lesson 2

Include the WorldWind library

We will use the WorldWind library hosted on the NASA servers. Add this line of code to the list of JavaScript scripts at the bottom of your web page, place it before the app.js script:

<script src="https://files.worldwind.arc.nasa.gov/artifactory/web/0.9.0/worldwind.min.js"></script>

Create the Globe class

Now we will create a Globe class to encapsulate the WorldWindow object (wwd).

In our web app we will be using layer categories to act on subsets of the WorldWindow.layers. We add layers to the WorldWindow via the Globe.addLayer function to assign a category and to update the layer’s properties via an options object. The Globe.addLayer function will conveniently apply all the properties of the options object to the layer.

Copy the following block of JavaScript to the app.js file.

JavaScript
/**
 * The Globe encapsulates the WorldWindow object (wwd) and provides application
 * specific logic for interacting with layers.
 * @param {String} canvasId The ID of the canvas element that will host the globe
 * @returns {Globe}
 */
class Globe {
  constructor(canvasId) {
    // Create a WorldWindow globe on the specified HTML5 canvas
    this.wwd = new WorldWind.WorldWindow(canvasId);

    // Holds the next unique id to be assigned to a layer
    this.nextLayerId = 1;

    // Add a BMNGOneImageLayer background layer. We're overriding the default 
    // minimum altitude of the BMNGOneImageLayer so this layer always available.
    this.addLayer(new WorldWind.BMNGOneImageLayer(), {
      category: "background",
      minActiveAltitude: 0
    });
  }

  /**
   * Adds a layer to the globe. Applies the optional options' properties to the
   * layer, and assigns the layer a unique ID and category.
   * @param {WorldWind.Layer} layer
   * @param {Object|null} options E.g., {category: "base", enabled: true}
   */
  addLayer(layer, options) {
    // Copy all properties defined on the options object to the layer
    if (options) {
      for (let prop in options) {
        if (!options.hasOwnProperty(prop)) {
          continue; // skip inherited props
        }
        layer[prop] = options[prop];
      }
    }
    // Assign a default category property if not already assigned
    if (typeof layer.category === 'undefined') {
      layer.category = 'overlay'; // the default category
    }

    // Assign a unique layer ID to ease layer management 
    layer.uniqueId = this.nextLayerId++;

    // Add the layer to the globe
    this.wwd.addLayer(layer);
  }

  /**
   * Returns a new array of layers in the given category.
   * @param {String} category E.g., "base", "overlay" or "setting".
   * @returns {Array}
   */
  getLayers(category) {
    return this.wwd.layers.filter(layer => layer.category === category);
  }
}

Now you can create a Globe object with it’s underlying WorldWindow like this:

let globe = new Globe("globe-canvas");

where “globe-canvas” is the name of a <canvas/> element in your HTML.

Create the globe and add layers

Now we will create a Globe object and add some layers to the globe. Some of the WorldWind layers require a WorldWindow object in their constructors (globe.wwd). This is one of the few cases where we access the wwd property outside of the Globe class.

Copy this block of JavaScript code the app.js file and paste it below the Globe class declaration.

JavaScript
  // Create a globe
  let globe = new Globe("globe-canvas");

  // Add layers to the globe 
  globe.addLayer(new WorldWind.BMNGLayer(), {
    category: "base"
  });
  globe.addLayer(new WorldWind.CoordinatesDisplayLayer(globe.wwd), {
    category: "setting"
  });
  globe.addLayer(new WorldWind.ViewControlsLayer(globe.wwd), {
    category: "setting"
  });
  globe.addLayer(new WorldWind.CompassLayer(), {
    category: "setting",
    enabled: false
  });

Summary

At this stage you have a functioning globe in the web app that responds to mouse and touch input.

Here’s the complete code for lesson 2: a web app prototype with a functioning globe and layers.


Next Steps