Configuring Cesium map application using webpack

When building web applications, you have several options and you probably know already, which libraries and build-stack you are going to use. You can find a lot of useful examples at the Sandcastle of the Cesium project. We will demonstrate, how to create a 3D web mapping application based on the cesium-webpack-example

Step 1: Install and run a minimal Cesium application using webpack

Webpack is the static module builder for JavaScript applications. It helps you with the development of the new application as well as with the creation of the distribution package.

Download and unzip the cesium-webpack-example package (either using the direct download link or using Git commands).

git clone https://github.com/maptiler/cesium-webpack-example.git
cd cesium-webpack-example

Then run the command, which should install all necessary dependencies.

npm install

And after all necessary packages are successfully downloaded, you can start the development server, which will make it easy to develop a custom 3D mapping application.

npm start

And open the link http://localhost:8080/ in your browser.

A basic example with Cesium data sources will pop up. Now let’s start hacking around this example. The sources are located in the src/ folder, the file src/index.js is of main interest:

import { Cesium3DTileset, createWorldTerrain, IonResource, Viewer } from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
import "./css/main.css";

var viewer = new Viewer('cesiumContainer', {
    terrainProvider: createWorldTerrain()
});

var tileset = new Cesium3DTileset({
    url: IonResource.fromAssetId(40866)
});

viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);

We will restructure the code, so it uses sources directed to MapTiler cloud services. Let’s start from scratch, and delete all the code, maybe except for the imports.

import { Cesium3DTileset, createWorldTerrain, IonResource, Viewer } from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
import "./css/main.css";

First, we need to define the TerrainProvider instance.

var terrain = new CesiumTerrainProvider({
  url: `https://api.maptiler.com/tiles/terrain-quantized-mesh/?key=${MAPTILER_API_KEY}`
});

As the second step, we need to define the ImageProvider - and we will use the URL reference to one of the Maptiler services, in this case, it will be the Outdoor map.

var outdoor = new UrlTemplateImageryProvider({
  url: `https://api.maptiler.com/maps/outdoor/{z}/{x}/{y}.png?key=${MAPTILER_API_KEY}`,
  minimumLevel: 0,
  maximumLevel: 20
});

We now have two important data sources: the terrain and the imagery overlay. This can be now plugged into the application. This can be done, using very complex Cesium.Viewer class or much simpler Cesium.Widget class.

var cesiumWidget = new CesiumWidget('cesiumContainer', 
  {
    imageryProvider: outdoor,
    terrainProvider: terrain
  }
);

Don’t forget to add used classes, which is CesiumTerrainProvider, UrlTemplateImageryProvider and the CesiumWidget to the import statement. The node server will reload automatically every time you change the code.

Now we just have to zoom to the desired location (e.g. Alps region), this is done with the help of the Camera object

viewer.camera.flyTo({
   destination: Cartesian3.fromDegrees(8.67, 46.72, 4300),
   orientation: { pitch: Math.toRadians(-20) }
});

The full example now looks like this:

import { Cesium3DTileset, createWorldTerrain, IonResource, CesiumTerrainProvider,
         UrlTemplateImageryProvider, Viewer, CesiumWidget, Cartesian3,
         Math } from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
import "./css/main.css";

var MAPTILER_API_KEY="XFXXXXXXXXXXXXXeeg";

var terrain = new CesiumTerrainProvider({
  url: `https://api.maptiler.com/tiles/terrain-quantized-mesh/?key=${MAPTILER_API_KEY}`
});

var outdoor = new UrlTemplateImageryProvider({
  url: `https://api.maptiler.com/maps/outdoor/{z}/{x}/{y}.png?key=${MAPTILER_API_KEY}`,
  minimumLevel: 0,
  maximumLevel: 20
});

var widget = new CesiumWidget('cesiumContainer', 
  {
    imageryProvider: outdoor,
    terrainProvider: terrain
  }
);

widget.camera.flyTo({
   destination: Cartesian3.fromDegrees(8.67, 46.72, 4300),
   orientation: { pitch: Math.toRadians(-20) }
});