3D globes: CesiumJS and orbital visualization
From 2D maps to 3D globes. CesiumJS is the open-source heavyweight champion. This week you put a real satellite into a real-time 3D orbital simulation.
When you imagine the ISS overhead, do you see it as a moving dot on a 2D map — or floating above Earth in 3D?
3D is closer to the truth. Cesium is the open-source 3D globe library that lets you put any data into orbital context. This week you'll fly your own.
Learning objectives
- Initialize a CesiumJS viewer in HTML
- Add an entity with a position track in time
- Draw an orbital path in 3D space
- Use Cesium's time slider for playback
Try it: orbit speed visualization
Lower orbits go faster; higher orbits go slower. This is Kepler's third law in action. Slide the altitude and watch the orbital speed update.
Primer
2D web maps work fine for showing where things are on Earth's surface. But satellites are NOT on Earth's surface — they're hundreds to thousands of kilometers above it, moving fast, in highly inclined orbits that wrap around the planet. To show where a satellite actually is in a way that makes intuitive sense, you need a 3D globe.
CesiumJS
CesiumJS (cesium.com) is the open-source 3D globe library that became the de-facto standard for serious 3D web GIS. NASA's Eyes on Asteroids, the FAA's traffic visualizations, every major satellite-tracker website with a 3D mode — all built on Cesium. The library is Apache 2.0 licensed; the commercial side is Cesium Ion, which hosts 3D tiles.
Cesium renders Earth as a WGS84 ellipsoid in WebGL. Coordinates are world-coordinate Cartesian (ECEF) internally; user-facing APIs accept lat/lon/altitude. The library handles all the camera math (orbit, zoom, tilt) so you don't have to.
Hello CesiumJS
<link rel="stylesheet" href="https://cesium.com/downloads/cesiumjs/releases/1.121/Build/Cesium/Widgets/widgets.css">
<script src="https://cesium.com/downloads/cesiumjs/releases/1.121/Build/Cesium/Cesium.js"></script>
<div id="cesiumContainer" style="width:100%;height:600px"></div>
<script>
Cesium.Ion.defaultAccessToken = 'your-ion-token-or-empty-for-offline';
const viewer = new Cesium.Viewer('cesiumContainer');
viewer.entities.add({
name: 'Cape Canaveral',
position: Cesium.Cartesian3.fromDegrees(-80.6, 28.6, 0),
point: { pixelSize: 10, color: Cesium.Color.ORANGE }
});
</script>
Entities, time, and SampledPositionProperty
An Entity is Cesium's unit of "a thing on the globe". It has a position (which can be a function of time), graphics (point, billboard, polyline, polygon, model, etc.), and metadata.
A satellite is an entity whose position changes over time. You provide a series of timestamped positions; Cesium interpolates between them. The interpolation can be linear, Lagrange, or Hermite — for orbital motion, Hermite with high degree gives the smoothest result.
const positions = new Cesium.SampledPositionProperty();
positions.setInterpolationOptions({
interpolationDegree: 7,
interpolationAlgorithm: Cesium.HermitePolynomialApproximation
});
// For each propagated point from skyfield (or satellite.js):
for (const {time, lon, lat, alt} of orbital_points) {
const jd = Cesium.JulianDate.fromIso8601(time);
const xyz = Cesium.Cartesian3.fromDegrees(lon, lat, alt * 1000);
positions.addSample(jd, xyz);
}
viewer.entities.add({
name: 'ISS',
position: positions,
point: { pixelSize: 10, color: Cesium.Color.CYAN },
path: { width: 2, material: Cesium.Color.CYAN.withAlpha(0.5),
leadTime: 0, trailTime: 5400 } // show 90-min trail
});
Time control
Cesium has a built-in Clock and an animation widget. The clock advances time; the SampledPositionProperty re-samples on each tick. The animation widget lets the user scrub, pause, and change playback speed.
viewer.clock.startTime = Cesium.JulianDate.fromIso8601('2026-05-11T00:00:00Z');
viewer.clock.stopTime = Cesium.JulianDate.fromIso8601('2026-05-12T00:00:00Z');
viewer.clock.currentTime = viewer.clock.startTime.clone();
viewer.clock.multiplier = 60; // 60x real time
viewer.clock.shouldAnimate = true;
Performance ceiling
Cesium can comfortably render ~10,000 simple entities at 60 fps on a modern desktop. Beyond that you need to use primitives (a lower-level API) instead of entities. The whole CelesTrak catalog (~10,000) renders fine; the Starlink constellation alone (~6,000) is also fine. Whole synthetic constellations of ~100,000 satellites need primitives.
The lab
You'll build a CesiumJS page that loads the current ISS TLE, uses satellite.js (the JavaScript SGP4 port) to propagate 24 hours, draws the orbital path as a polyline, and animates the ISS along it with the Cesium time control. By the end you'll have a working real-time satellite tracker — the foundation for Capstone 4 in Week 20.
Connecting to Hawaiʻi: 3D globes and the wayfinding mindset
When Polynesian wayfinders teach navigation, they often start by having students imagine themselves standing still while the stars and the Earth move around them. The instinct for 3D-spatial-mental-models is deep in Hawaiian navigational tradition. Cesium reflects that perspective: it shows Earth as a 3D body in space, not a flat map. The same skill that helps a wayfinder visualize wind cells and ocean swells helps a programmer reason about orbital geometry.
Hands-on lab: ISS in 3D
Build a CesiumJS web page that loads the current ISS TLE, propagates 24 hours, draws the orbital path as a polyline, and animates the ISS along it with the Cesium time control.
Quiz — click an answer to check it
No grade, no shame. Tap any option; you'll see if it's right plus the answer if not. The point is to notice what you already know and what's still settling.
- WebGL
- Canvas 2D
- SVG
- DOM
- WGS84 (matching GPS)
- Web Mercator
- UTM
- Local tangent plane
- A position (possibly time-dependent), graphics, and metadata
- Only a position
- Only graphics
- Only metadata
- A 3D tile hosting service from Cesium (commercial)
- A free CDN
- A Cesium fork
- A QGIS plugin
- Clock + SampledPositionProperty
- setTimeout loop
- CSS animations
- WebSocket only
Reflection
Take five minutes with this. Write your answer somewhere. Carry it into next week.