# CesiumJS CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin. It uses WebGL for hardware-accelerated graphics, and is cross-platform, cross-browser, and tuned for dynamic-data visualization. Built on open formats, CesiumJS is designed for robust interoperability and scaling for massive datasets. The library provides comprehensive support for streaming 3D Tiles and other standard formats, visualizing and analyzing data on a high-precision WGS84 globe, and sharing applications with users on desktop or mobile. CesiumJS can stream 3D content such as terrain, imagery, and 3D Tiles from Cesium ion or other sources, making it the go-to solution for geospatial 3D visualization on the web. ## Installation ```bash npm install cesium --save ``` ## Basic Usage - Creating a Viewer The Viewer widget is the primary way to create a CesiumJS application with all standard UI controls. ```javascript import { Viewer } from "cesium"; import "cesium/Build/Cesium/Widgets/widgets.css"; // Create a basic viewer const viewer = new Viewer("cesiumContainer"); // Create viewer with custom options const viewer = new Cesium.Viewer("cesiumContainer", { sceneMode: Cesium.SceneMode.COLUMBUS_VIEW, terrain: Cesium.Terrain.fromWorldTerrain(), baseLayerPicker: false, baseLayer: new Cesium.ImageryLayer(new Cesium.OpenStreetMapImageryProvider({ url: "https://tile.openstreetmap.org/" })), animation: true, timeline: true, fullscreenButton: true, geocoder: true }); ``` ## CesiumWidget - Lightweight 3D Globe CesiumWidget provides the core rendering engine without the full Viewer UI. Use this for custom applications that don't need standard widgets. ```javascript import { CesiumWidget } from "@cesium/engine"; import "@cesium/engine/Source/Widget/CesiumWidget.css"; // Create a lightweight 3D globe widget const cesiumWidget = new CesiumWidget("cesiumContainer"); // Access the scene and camera directly const scene = cesiumWidget.scene; const camera = cesiumWidget.camera; ``` ## Camera Control - setView The `setView` method immediately sets the camera position and orientation without animation. ```javascript // Set position with a top-down view using Cartesian coordinates viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0) }); // Set view with heading, pitch and roll orientation viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0), orientation: { heading: Cesium.Math.toRadians(90.0), // east pitch: Cesium.Math.toRadians(-45), // looking down at 45 degrees roll: 0.0 } }); // View a rectangle (bounding box) from above viewer.camera.setView({ destination: Cesium.Rectangle.fromDegrees(-100.0, 30.0, -90.0, 40.0) }); // Set orientation using direction and up vectors viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0), orientation: { direction: new Cesium.Cartesian3(-0.04231, -0.20123, -0.97862), up: new Cesium.Cartesian3(-0.47934, -0.85532, 0.19660) } }); ``` ## Camera Control - flyTo The `flyTo` method smoothly animates the camera from the current position to a new destination. ```javascript // Fly to a position with default duration viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0) }); // Fly to a rectangle viewer.camera.flyTo({ destination: Cesium.Rectangle.fromDegrees(-100.0, 30.0, -90.0, 40.0) }); // Fly with custom orientation and duration viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 5000.0), orientation: { heading: Cesium.Math.toRadians(175.0), pitch: Cesium.Math.toRadians(-35.0), roll: 0.0 }, duration: 3.0, // seconds complete: function() { console.log("Flight complete!"); }, cancel: function() { console.log("Flight cancelled"); } }); ``` ## Camera Control - lookAt The `lookAt` method positions the camera to look at a specific target point. ```javascript // Look at a target from an offset position const center = Cesium.Cartesian3.fromDegrees(-98.0, 40.0); viewer.camera.lookAt(center, new Cesium.Cartesian3(0.0, -4790000.0, 3930000.0)); // Look at using heading, pitch, and range const heading = Cesium.Math.toRadians(50.0); const pitch = Cesium.Math.toRadians(-20.0); const range = 5000.0; viewer.camera.lookAt( center, new Cesium.HeadingPitchRange(heading, pitch, range) ); // Reset to free camera mode after lookAt viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); ``` ## Entity API - Creating Visual Objects Entities provide a high-level API for creating and managing visual objects with automatic LOD and animation support. ```javascript // Add a point entity const pointEntity = viewer.entities.add({ name: "Sample Point", position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 100), point: { pixelSize: 10, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 }, label: { text: "Philadelphia", font: "14pt monospace", style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -9) } }); // Add a polygon entity const polygonEntity = viewer.entities.add({ name: "Sample Polygon", polygon: { hierarchy: Cesium.Cartesian3.fromDegreesArray([ -115.0, 37.0, -115.0, 32.0, -107.0, 33.0, -102.0, 31.0, -102.0, 35.0 ]), material: Cesium.Color.RED.withAlpha(0.5), outline: true, outlineColor: Cesium.Color.BLACK, extrudedHeight: 100000 // extrude to this height } }); // Add a polyline entity const lineEntity = viewer.entities.add({ name: "Sample Line", polyline: { positions: Cesium.Cartesian3.fromDegreesArrayHeights([ -75, 35, 0, -125, 35, 0, -125, 35, 100000 ]), width: 5, material: new Cesium.PolylineGlowMaterialProperty({ glowPower: 0.2, color: Cesium.Color.BLUE }) } }); // Zoom to entity viewer.zoomTo(polygonEntity); ``` ## Billboard and Model Entities Billboards display images that always face the camera, while models load 3D glTF assets. ```javascript // Add a billboard entity const billboardEntity = viewer.entities.add({ name: "Billboard", position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), billboard: { image: "path/to/image.png", width: 64, height: 64, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND } }); // Add a 3D model entity const modelEntity = viewer.entities.add({ name: "Cesium Man", position: Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000.0), model: { uri: "path/to/model.glb", minimumPixelSize: 128, maximumScale: 20000, scale: 1.0 } }); ``` ## Loading 3D Tiles Load massive 3D datasets using the Cesium3DTileset class for optimized streaming and rendering. ```javascript // Load a 3D Tileset from URL try { const tileset = await Cesium.Cesium3DTileset.fromUrl( "http://localhost:8002/tilesets/Seattle/tileset.json" ); viewer.scene.primitives.add(tileset); viewer.zoomTo(tileset); } catch (error) { console.error(`Error creating tileset: ${error}`); } // Load from Cesium ion asset try { const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(69380); viewer.scene.primitives.add(tileset); viewer.zoomTo(tileset); } catch (error) { console.error(`Error loading ion asset: ${error}`); } // Load with optimization settings const tileset = await Cesium.Cesium3DTileset.fromUrl( "http://localhost:8002/tilesets/Building/tileset.json", { maximumScreenSpaceError: 16, dynamicScreenSpaceError: true, dynamicScreenSpaceErrorDensity: 2.0e-4, dynamicScreenSpaceErrorFactor: 24.0, dynamicScreenSpaceErrorHeightFalloff: 0.25, enableCollision: true } ); viewer.scene.primitives.add(tileset); ``` ## Loading glTF Models Load 3D models using the Model class for direct control over glTF assets. ```javascript // Load a glTF model try { const model = await Cesium.Model.fromGltfAsync({ url: "../../SampleData/models/CesiumMan/Cesium_Man.glb" }); viewer.scene.primitives.add(model); } catch (error) { console.log(`Failed to load model. ${error}`); } // Load with positioning and sizing const position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000.0); const headingPitchRoll = new Cesium.HeadingPitchRoll(); const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator("north", "west"); try { const model = await Cesium.Model.fromGltfAsync({ url: "../../SampleData/models/CesiumAir/Cesium_Air.glb", modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame( position, headingPitchRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform ), minimumPixelSize: 128, maximumScale: 20000 }); viewer.scene.primitives.add(model); } catch (error) { console.log(`Failed to load model. ${error}`); } ``` ## GeoJSON Data Loading Load and visualize GeoJSON data using the GeoJsonDataSource class. ```javascript // Load GeoJSON from URL const dataSource = await Cesium.GeoJsonDataSource.load("path/to/data.geojson", { stroke: Cesium.Color.HOTPINK, fill: Cesium.Color.PINK.withAlpha(0.5), strokeWidth: 3, markerSymbol: "?" }); viewer.dataSources.add(dataSource); viewer.zoomTo(dataSource); // Load GeoJSON from object const geojsonData = { type: "FeatureCollection", features: [{ type: "Feature", geometry: { type: "Point", coordinates: [-75.59777, 40.03883] }, properties: { name: "Philadelphia" } }] }; const dataSource = await Cesium.GeoJsonDataSource.load(geojsonData); viewer.dataSources.add(dataSource); // Access loaded entities dataSource.entities.values.forEach(entity => { console.log(entity.name, entity.properties); }); ``` ## KML Data Loading Load KML and KMZ files using the KmlDataSource class. ```javascript // Load KML file try { const dataSource = await Cesium.KmlDataSource.load("path/to/file.kml", { camera: viewer.scene.camera, canvas: viewer.scene.canvas, clampToGround: true }); viewer.dataSources.add(dataSource); viewer.zoomTo(dataSource); } catch (error) { console.error("Error loading KML:", error); } // Load KMZ file (compressed KML) const dataSource = await Cesium.KmlDataSource.load("path/to/file.kmz", { camera: viewer.scene.camera, canvas: viewer.scene.canvas }); viewer.dataSources.add(dataSource); ``` ## CZML Data Loading Load time-dynamic data using the CZML format. ```javascript // Load CZML from URL const dataSource = await Cesium.CzmlDataSource.load("path/to/data.czml"); viewer.dataSources.add(dataSource); viewer.zoomTo(dataSource); // Load CZML from object const czmlData = [{ id: "document", name: "CZML Sample", version: "1.0", clock: { interval: "2012-03-15T10:00:00Z/2012-03-16T10:00:00Z", currentTime: "2012-03-15T10:00:00Z", multiplier: 60 } }, { id: "vehicle", name: "Vehicle", availability: "2012-03-15T10:00:00Z/2012-03-16T10:00:00Z", position: { cartographicDegrees: [ "2012-03-15T10:00:00Z", -75.0, 40.0, 0, "2012-03-15T10:30:00Z", -76.0, 41.0, 0 ] }, point: { color: { rgba: [255, 255, 0, 255] }, pixelSize: 10 } }]; const dataSource = await Cesium.CzmlDataSource.load(czmlData); viewer.dataSources.add(dataSource); ``` ## Terrain Provider Configure terrain for realistic globe elevation. ```javascript // Use Cesium World Terrain from ion viewer.terrain = Cesium.Terrain.fromWorldTerrain({ requestVertexNormals: true, requestWaterMask: true }); // Create terrain provider directly const terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl( Cesium.IonResource.fromAssetId(1), { requestVertexNormals: true, requestWaterMask: true } ); viewer.terrainProvider = terrainProvider; // Use ellipsoid terrain (flat globe) viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider(); ``` ## Imagery Layers Add and manage imagery layers on the globe. ```javascript // Access the imagery layer collection const imageryLayers = viewer.imageryLayers; // Add OpenStreetMap imagery const osmProvider = new Cesium.OpenStreetMapImageryProvider({ url: "https://tile.openstreetmap.org/" }); imageryLayers.addImageryProvider(osmProvider); // Add Bing Maps imagery const bingProvider = await Cesium.BingMapsImageryProvider.fromUrl( "https://dev.virtualearth.net", { key: "YOUR_BING_MAPS_KEY", mapStyle: Cesium.BingMapsStyle.AERIAL } ); imageryLayers.addImageryProvider(bingProvider); // Add ArcGIS imagery const arcGisProvider = await Cesium.ArcGisMapServerImageryProvider.fromUrl( "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer" ); imageryLayers.addImageryProvider(arcGisProvider); // Adjust layer properties const layer = imageryLayers.get(0); layer.alpha = 0.5; // transparency layer.brightness = 1.5; // brightness layer.contrast = 1.2; // contrast layer.show = true; // visibility ``` ## Scene Picking Pick objects and terrain positions from screen coordinates. ```javascript // Pick an entity or primitive const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas); handler.setInputAction(function(click) { const pickedObject = viewer.scene.pick(click.position); if (Cesium.defined(pickedObject)) { if (pickedObject.id instanceof Cesium.Entity) { console.log("Picked entity:", pickedObject.id.name); } else if (pickedObject instanceof Cesium.Cesium3DTileFeature) { console.log("Picked 3D Tile feature"); const propertyIds = pickedObject.getPropertyIds(); propertyIds.forEach(id => { console.log(`${id}: ${pickedObject.getProperty(id)}`); }); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); // Pick position on globe/terrain handler.setInputAction(function(movement) { const cartesian = viewer.camera.pickEllipsoid( movement.endPosition, viewer.scene.globe.ellipsoid ); if (cartesian) { const cartographic = Cesium.Cartographic.fromCartesian(cartesian); const longitude = Cesium.Math.toDegrees(cartographic.longitude); const latitude = Cesium.Math.toDegrees(cartographic.latitude); console.log(`Position: ${longitude}, ${latitude}`); } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // Pick with ray for terrain height const ray = viewer.camera.getPickRay(windowPosition); const intersection = viewer.scene.globe.pick(ray, viewer.scene); ``` ## Clock and Time Animation Control simulation time for time-dynamic data. ```javascript // Access the clock const clock = viewer.clock; // Set simulation time range clock.startTime = Cesium.JulianDate.fromIso8601("2024-01-01T00:00:00Z"); clock.stopTime = Cesium.JulianDate.fromIso8601("2024-01-02T00:00:00Z"); clock.currentTime = Cesium.JulianDate.fromIso8601("2024-01-01T12:00:00Z"); // Control playback clock.shouldAnimate = true; // start animation clock.multiplier = 3600; // 1 hour per second clock.clockRange = Cesium.ClockRange.LOOP_STOP; // loop when reaching end // React to time changes clock.onTick.addEventListener(function(clock) { const currentTime = Cesium.JulianDate.toDate(clock.currentTime); console.log("Current simulation time:", currentTime); }); ``` ## Event Handling Handle user interactions with the globe. ```javascript // Screen space events const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas); // Left click handler.setInputAction(function(click) { console.log("Left click at:", click.position); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); // Right click handler.setInputAction(function(click) { console.log("Right click at:", click.position); }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); // Mouse move handler.setInputAction(function(movement) { console.log("Mouse at:", movement.endPosition); }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // Camera change events viewer.camera.changed.addEventListener(function() { console.log("Camera moved"); }); viewer.camera.moveEnd.addEventListener(function() { console.log("Camera movement ended"); }); // Entity selection viewer.selectedEntityChanged.addEventListener(function(entity) { if (entity) { console.log("Selected:", entity.name); } }); // Cleanup handler.destroy(); ``` ## Summary CesiumJS excels at visualizing geospatial data in 3D web applications. The main use cases include: displaying massive 3D datasets using 3D Tiles for buildings, terrain, and point clouds; creating interactive maps with time-dynamic data using CZML; loading and styling vector data from GeoJSON, KML, and other formats; and building custom geospatial applications with precise camera control and picking capabilities. Integration patterns typically involve creating a Viewer instance as the application's foundation, adding data sources for various formats (GeoJSON, KML, CZML, 3D Tiles), configuring terrain and imagery layers for realistic visualization, and implementing event handlers for user interaction. The Entity API provides a high-level interface for most visualization needs, while the Primitive API offers lower-level control for performance-critical applications. CesiumJS integrates well with modern JavaScript frameworks and build systems through its npm package distribution.