🇮🇹 Cesium.js — Guida Completa alla Visualizzazione Geospaziale 3D per il Web
Introduzione: Il Mondo in 3D nel Tuo Browser
Immagina di poter esplorare un modello tridimensionale dell'intero pianeta Terra direttamente dal browser, senza installare alcun plugin. Di sorvolare città con edifici 3D fotorealistici, analizzare terreni montani con precisione centimetrica, o tracciare in tempo reale il volo di un aereo da San Francisco a Copenaghen. Tutto questo è possibile grazie a CesiumJS, la libreria JavaScript open source che ha ridefinito la visualizzazione geospaziale sul web.
CesiumJS è molto più di una semplice libreria di mappe: è un vero e proprio motore 3D geospaziale progettato per offrire prestazioni elevate, precisione scientifica e qualità visiva di livello professionale. Dalla sua nascita nel 2012, è diventato lo standard de facto per chi ha bisogno di visualizzare dati geospaziali tridimensionali in ambiti che spaziano dall'aerospazio alla pianificazione urbana, dalla difesa alla gestione dei droni.
In questa guida completa esploreremo ogni aspetto di CesiumJS: dall'architettura interna alle funzionalità principali, dalla configurazione iniziale agli esempi avanzati, fino ai casi d'uso reali che dimostrano la potenza di questa libreria. Che tu sia uno sviluppatore web, un professionista GIS o un appassionato di tecnologia geospaziale, troverai tutto ciò che serve per iniziare a costruire applicazioni 3D straordinarie.
Sezione 1: Cos'è CesiumJS e Perché è Importante
CesiumJS è una libreria JavaScript rilasciata sotto licenza Apache 2.0, quindi completamente gratuita sia per uso commerciale che non commerciale. Sfrutta WebGL per l'accelerazione hardware della grafica, il che significa che qualsiasi browser moderno può renderizzare globi 3D complessi senza dipendenze esterne.
Il cuore della filosofia di Cesium è l'interoperabilità basata su standard aperti. Invece di creare formati proprietari, il team di Cesium ha sviluppato e promosso specifiche aperte come 3D Tiles (ora standard OGC) e si appoggia a formati consolidati come glTF, KML, GeoJSON e CZML. Questo approccio garantisce che i dati rimangano portabili e che l'ecosistema sia accessibile a tutti.
L'architettura è pensata per gestire dataset massivi attraverso lo streaming progressivo: invece di caricare interi modelli in memoria, CesiumJS carica dinamicamente solo le porzioni di dati visibili all'utente, adattando il livello di dettaglio in base alla distanza della camera. Questa tecnica consente di visualizzare intere città con milioni di edifici, nuvole di punti con miliardi di punti, o modelli di terreno a risoluzione globale, il tutto senza sacrificare la fluidità dell'interazione.
// Esempio minimo: creare un globo CesiumJS
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
// Questo è tutto ciò che serve per avere un globo 3D interattivo!
Con sole tre righe di codice hai un globo terrestre 3D interattivo con terreno ad alta risoluzione, navigazione con mouse e touch, e accesso ai widget integrati di CesiumJS. Da qui puoi costruire qualsiasi tipo di applicazione geospaziale.
Sezione 2: L'Ecosistema Cesium — CesiumJS e Cesium ion
È fondamentale distinguere tra i due componenti principali dell'ecosistema Cesium, perché svolgono ruoli complementari ma distinti.
CesiumJS è il motore di rendering client-side: la libreria JavaScript che si occupa di disegnare il globo, gestire la camera, renderizzare i tile 3D e gestire l'interazione utente. È completamente open source e può essere utilizzato in modo indipendente, collegandosi a qualsiasi server di tile compatibile.
Cesium ion è invece la piattaforma cloud (SaaS) che si occupa di ospitare, ottimizzare e servire dati geospaziali in formato 3D Tiles. Quando crei un account gratuito su Cesium ion, ottieni accesso immediato a contenuti globali precaricati come:
- Cesium World Terrain — un modello di elevazione del terreno ad alta risoluzione che copre l'intero pianeta, includendo dati bathymetrici oceanici.
- Cesium OSM Buildings — un layer globale di edifici 3D derivato da OpenStreetMap, con oltre 350 milioni di strutture.
- Bing Maps Imagery — immagini satellitari ad alta risoluzione utilizzabili come base layer per il globo.
Cesium ion offre anche pipeline di tiling che trasformano automaticamente i tuoi dati (fotogrammetria, nuvole di punti LiDAR, modelli BIM/CAD) nel formato 3D Tiles ottimizzato per lo streaming. L'account gratuito è sufficiente per progetti di sviluppo e prototipazione, mentre i piani a pagamento sono destinati ad applicazioni in produzione con volumi di traffico elevati.
// Configurare il token di accesso a Cesium ion
Cesium.Ion.defaultAccessToken = 'IL_TUO_ACCESS_TOKEN';
// Il token abilita l'accesso ai contenuti globali:
// - Cesium World Terrain (asset ID: 1)
// - Cesium OSM Buildings (asset ID: 96188)
// - Bing Maps Aerial Imagery
// - I tuoi asset personalizzati caricati su ion
Sezione 3: Setup via CDN — Il Modo Più Rapido per Iniziare
Scenario: Vuoi creare rapidamente una pagina HTML con un globo 3D interattivo senza configurare alcun tool di build.
Il metodo CDN è perfetto per prototipi, demo e per imparare le basi di CesiumJS. Basta includere il file JavaScript e il foglio di stile CSS direttamente dalla CDN ufficiale di Cesium.
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8">
<title>La Mia Prima App CesiumJS</title>
<!-- Includi CesiumJS dalla CDN ufficiale -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.139.1/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.139.1/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<style>
html, body, #cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script type="module">
// Sostituisci con il tuo token da https://ion.cesium.com/tokens
Cesium.Ion.defaultAccessToken = 'IL_TUO_ACCESS_TOKEN';
// Inizializza il Viewer con terreno mondiale
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
// Vola verso Roma
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 800),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-20.0),
}
});
// Aggiungi edifici 3D globali (OpenStreetMap)
const buildings = await Cesium.createOsmBuildingsAsync();
viewer.scene.primitives.add(buildings);
</script>
</body>
</html>
✅ Risultato: Aprendo questo file nel browser vedrai il globo terrestre volare verso Roma con gli edifici 3D visibili. L'intera scena è interattiva: puoi ruotare, zoomare e inclinare la vista con mouse o touch.
Sezione 4: Setup via NPM — Per Progetti Strutturati
Scenario: Stai costruendo un'applicazione web moderna con un framework come React, Angular o Vue, e utilizzi un module bundler come Webpack, Vite o Rollup.
# Installazione tramite npm
npm install cesium
# oppure con yarn
yarn add cesium
# oppure con pnpm
pnpm add cesium
// IMPORTANTE: CESIUM_BASE_URL deve essere impostato PRIMA dell'import
window.CESIUM_BASE_URL = '/';
import {
Cartesian3,
createOsmBuildingsAsync,
Ion,
Math as CesiumMath,
Terrain,
Viewer
} from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
// Configura il token di accesso
Ion.defaultAccessToken = 'IL_TUO_ACCESS_TOKEN';
// Inizializza il Viewer
const viewer = new Viewer('cesiumContainer', {
terrain: Terrain.fromWorldTerrain(),
});
// Vola verso Roma
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(12.4964, 41.9028, 800),
orientation: {
heading: CesiumMath.toRadians(0.0),
pitch: CesiumMath.toRadians(-20.0),
}
});
// Aggiungi edifici 3D
const buildings = await createOsmBuildingsAsync();
viewer.scene.primitives.add(buildings);
Quando si utilizza NPM, è necessario configurare il bundler per servire come
file statici le seguenti directory dalla cartella
node_modules/cesium/Build/Cesium/:
Workers— Web workers per calcoli off-threadThirdParty— Librerie di terze partiAssets— Icone, immagini e risorse graficheWidgets— Fogli di stile e risorse dei widget
✅ Risultato: Un setup pulito e modulare, compatibile con tree-shaking e ottimizzazione del bundle per la produzione.
Sezione 5: Configurazione del Viewer — Opzioni e Personalizzazione
Scenario: Vuoi personalizzare l'aspetto e il comportamento del globo: nascondere widget non necessari, cambiare il layer di immagini base, configurare le opzioni di rendering.
// Viewer con configurazione completa
const viewer = new Cesium.Viewer('cesiumContainer', {
// Terreno
terrain: Cesium.Terrain.fromWorldTerrain({
requestWaterMask: true, // Maschera per gli oceani
requestVertexNormals: true // Illuminazione realistica del terreno
}),
// Widget UI
animation: false, // Nascondi il widget di animazione
timeline: false, // Nascondi la timeline
fullscreenButton: true, // Mostra il pulsante fullscreen
vrButton: false, // Nascondi il pulsante VR
geocoder: true, // Mostra la barra di ricerca
homeButton: true, // Mostra il pulsante home
navigationHelpButton: false, // Nascondi l'aiuto navigazione
baseLayerPicker: true, // Mostra il selettore di layer base
sceneModePicker: true, // Mostra il selettore 3D/2D/Columbus
// Rendering
shadows: true, // Abilita le ombre
shouldAnimate: true, // Abilita le animazioni
useBrowserRecommendedResolution: true,
// Orologio (per dati time-dynamic)
clockViewModel: new Cesium.ClockViewModel(
new Cesium.Clock({
startTime: Cesium.JulianDate.fromIso8601('2025-01-01'),
stopTime: Cesium.JulianDate.fromIso8601('2025-12-31'),
currentTime: Cesium.JulianDate.fromIso8601('2025-06-15'),
clockRange: Cesium.ClockRange.LOOP_STOP,
multiplier: 1
})
)
});
// Personalizzare lo sfondo del cielo
viewer.scene.skyBox = new Cesium.SkyBox({
sources: {
positiveX: 'stars/px.jpg',
negativeX: 'stars/nx.jpg',
positiveY: 'stars/py.jpg',
negativeY: 'stars/ny.jpg',
positiveZ: 'stars/pz.jpg',
negativeZ: 'stars/nz.jpg'
}
});
// Abilitare l'atmosfera
viewer.scene.skyAtmosphere.show = true;
viewer.scene.fog.enabled = true;
viewer.scene.fog.density = 0.0002;
✅ Risultato: Un viewer completamente personalizzato con ombre realistiche, atmosfera, nebbia e widget selezionati in base alle esigenze dell'applicazione.
Sezione 6: 3D Tiles — Lo Standard per Dataset Massivi
Scenario: Hai un modello fotogrammetrico di un'intera città, una nuvola di punti LiDAR con miliardi di punti, o un dataset di edifici 3D. Vuoi visualizzarlo nel browser in modo fluido.
La specifica 3D Tiles, sviluppata originariamente dal team di Cesium e successivamente adottata come standard dall'Open Geospatial Consortium (OGC), è il formato chiave per lo streaming di dati 3D geospaziali su larga scala. Il sistema di Level-of-Detail gerarchico garantisce che solo i dati necessari vengano caricati.
// Caricare un tileset 3D Tiles da Cesium ion
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188);
viewer.scene.primitives.add(tileset);
// Zoom automatico sul tileset
viewer.zoomTo(tileset);
// Applicare uno stile condizionale ai 3D Tiles
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${height} > 100", "color('red')"],
["${height} > 50", "color('orange')"],
["${height} > 20", "color('yellow')"],
["true", "color('white')"]
]
},
show: "${height} > 0"
});
// Caricare 3D Tiles da un URL personalizzato (non Cesium ion)
const customTileset = await Cesium.Cesium3DTileset.fromUrl(
'https://mio-server.com/tileset/tileset.json',
{
maximumScreenSpaceError: 16, // Controlla il livello di dettaglio
maximumMemoryUsage: 512, // Limite di memoria in MB
dynamicScreenSpaceError: true, // LOD adattivo in movimento
skipLevelOfDetail: true // Salta livelli per caricamento più veloce
}
);
viewer.scene.primitives.add(customTileset);
✅ Risultato: Dataset di qualsiasi dimensione visualizzati in modo fluido grazie allo streaming progressivo e al Level-of-Detail adattivo.
Sezione 7: Terreno e Layer di Immagini
Scenario: Vuoi visualizzare il terreno realistico della Terra con montagne, valli e fondali oceanici, sovrapponendo diversi layer di immagini satellitari.
// Il Cesium World Terrain include:
// - Dati di elevazione ad alta risoluzione
// - Dati bathymetrici (profondità oceaniche)
// - Normali dei vertici per illuminazione realistica
// - Maschera acqua per effetti di riflessione
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain({
requestWaterMask: true,
requestVertexNormals: true
})
});
// Aggiungere un layer di immagini personalizzato
const imageryLayer = viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
minimumLevel: 0,
maximumLevel: 19,
credit: '© OpenStreetMap contributors'
})
);
// Regolare la trasparenza del layer
imageryLayer.alpha = 0.7;
// Aggiungere un layer WMS (Web Map Service)
const wmsLayer = viewer.imageryLayers.addImageryProvider(
new Cesium.WebMapServiceImageryProvider({
url: 'https://ows.terrestris.de/osm/service',
layers: 'OSM-WMS',
parameters: {
transparent: true,
format: 'image/png'
}
})
);
// Terreno personalizzato da un server proprio
const customTerrain = await Cesium.CesiumTerrainProvider.fromUrl(
'https://mio-server.com/terrain',
{
requestWaterMask: true,
requestVertexNormals: true
}
);
viewer.scene.setTerrain(new Cesium.Terrain(customTerrain));
// Abilitare il depth test contro il terreno
// (le entità dietro le colline non vengono mostrate)
viewer.scene.globe.depthTestAgainstTerrain = true;
✅ Risultato: Un globo con terreno realistico e multipli layer di immagini sovrapposti, con controllo completo su trasparenza, luminosità e ordine dei layer.
Sezione 8: Entità e Geometrie — Marker, Poligoni, Linee
Scenario: Vuoi aggiungere punti di interesse, aree delimitate, percorsi e altre informazioni geospaziali al tuo globo 3D.
// Aggiungere un marker con popup informativo
viewer.entities.add({
name: 'Colosseo',
position: Cesium.Cartesian3.fromDegrees(12.4924, 41.8902, 0),
point: {
pixelSize: 12,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
},
label: {
text: 'Colosseo',
font: '16px Helvetica',
fillColor: Cesium.Color.WHITE,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15),
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
},
description: '<h3>Colosseo</h3><p>Anfiteatro Flavio, simbolo di Roma.</p>'
});
// Aggiungere un billboard (icona personalizzata)
viewer.entities.add({
name: 'Fontana di Trevi',
position: Cesium.Cartesian3.fromDegrees(12.4833, 41.9009, 0),
billboard: {
image: '/icons/landmark.png',
width: 32,
height: 32,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
});
// Disegnare un poligono con estrusione 3D
viewer.entities.add({
name: 'Centro Storico di Roma',
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
12.470, 41.898,
12.505, 41.898,
12.505, 41.880,
12.470, 41.880
]),
material: Cesium.Color.BLUE.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.BLUE,
extrudedHeight: 50,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
});
// Disegnare una polilinea (percorso)
viewer.entities.add({
name: 'Percorso Turistico',
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
12.4924, 41.8902, // Colosseo
12.4833, 41.9009, // Fontana di Trevi
12.4534, 41.9029, // Vaticano
]),
width: 4,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.2,
color: Cesium.Color.YELLOW
}),
clampToGround: true
}
});
// Disegnare un cilindro 3D
viewer.entities.add({
name: 'Area di Copertura',
position: Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 200),
cylinder: {
length: 400,
topRadius: 200,
bottomRadius: 200,
material: Cesium.Color.GREEN.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.GREEN
}
});
// Disegnare un'ellisse (cerchio geospaziale)
viewer.entities.add({
name: 'Raggio di Ricerca',
position: Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 0),
ellipse: {
semiMajorAxis: 500,
semiMinorAxis: 500,
material: Cesium.Color.RED.withAlpha(0.2),
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
});
✅ Risultato: Un globo ricco di informazioni geospaziali interattive con marker, aree, percorsi e forme 3D. Cliccando su ogni entità appare un popup con la descrizione.
Sezione 9: Modelli 3D con glTF
Scenario: Vuoi posizionare un modello 3D (un edificio, un veicolo, un drone) sul globo con posizione, orientamento e scala precisi.
// Caricare un modello glTF da URL
const modelEntity = viewer.entities.add({
name: 'Modello 3D',
position: Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 50),
model: {
uri: '/models/building.glb',
minimumPixelSize: 64,
maximumScale: 20000,
silhouetteColor: Cesium.Color.YELLOW,
silhouetteSize: 2,
color: Cesium.Color.WHITE,
colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
}
});
// Caricare un modello da Cesium ion
const ionModel = viewer.entities.add({
name: 'Modello da ion',
position: Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 0),
model: {
uri: await Cesium.IonResource.fromAssetId(YOUR_ASSET_ID),
minimumPixelSize: 128
}
});
// Modello 3D con orientamento specifico
const position = Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 100);
const heading = Cesium.Math.toRadians(45); // rotazione orizzontale
const pitch = Cesium.Math.toRadians(0); // inclinazione
const roll = Cesium.Math.toRadians(0); // rollio
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
new Cesium.HeadingPitchRoll(heading, pitch, roll)
);
viewer.entities.add({
name: 'Aereo',
position: position,
orientation: orientation,
model: {
uri: '/models/airplane.glb',
minimumPixelSize: 64,
runAnimations: true // Avvia le animazioni del modello
}
});
✅ Risultato: Modelli 3D posizionati con precisione geospaziale, con supporto per animazioni, materiali PBR e illuminazione realistica.
Sezione 10: Visualizzazione Time-Dynamic (4D)
Scenario: Vuoi visualizzare dati che cambiano nel tempo: il percorso di un satellite, la rotta di un volo, la propagazione di un fenomeno meteorologico.
// Creare un'entità che si muove nel tempo
const start = Cesium.JulianDate.fromIso8601('2025-01-01T00:00:00Z');
const stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate());
// Configurare il clock
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
viewer.clock.multiplier = 10;
// Creare la posizione che cambia nel tempo
const positionProperty = new Cesium.SampledPositionProperty();
// Aggiungere campioni di posizione
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 0, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 10000) // Roma
);
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 120, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(2.3522, 48.8566, 11000) // Parigi
);
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 240, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(-3.7038, 40.4168, 10500) // Madrid
);
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 10000) // Ritorno a Roma
);
// Creare l'entità in movimento
const airplane = viewer.entities.add({
name: 'Volo Europa',
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({ start: start, stop: stop })
]),
position: positionProperty,
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
model: {
uri: '/models/airplane.glb',
minimumPixelSize: 64
},
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.CYAN
}),
width: 3
}
});
// Seguire l'entità con la camera
viewer.trackedEntity = airplane;
✅ Risultato: Un aereo animato che percorre la rotta Roma → Parigi → Madrid → Roma, con una scia luminosa e la camera che lo segue automaticamente. La timeline permette di avanzare, tornare indietro e regolare la velocità della simulazione.
Sezione 11: Formato CZML — Dati Geospaziali Temporali in JSON
Scenario: Vuoi descrivere scene complesse con dati time-dynamic in un formato dichiarativo JSON, senza scrivere codice procedurale.
// CZML è un formato JSON specifico di CesiumJS per dati time-dynamic
const czml = [
{
"id": "document",
"name": "Tracciamento Satellite",
"version": "1.0",
"clock": {
"interval": "2025-01-01T00:00:00Z/2025-01-01T01:00:00Z",
"currentTime": "2025-01-01T00:00:00Z",
"multiplier": 60
}
},
{
"id": "satellite-1",
"name": "ISS",
"description": "Stazione Spaziale Internazionale",
"billboard": {
"image": "/icons/satellite.png",
"scale": 0.5
},
"label": {
"text": "ISS",
"font": "14px sans-serif",
"fillColor": { "rgba": [255, 255, 0, 255] }
},
"position": {
"epoch": "2025-01-01T00:00:00Z",
"cartographicDegrees": [
0, 12.49, 41.90, 408000,
900, 45.00, 35.00, 410000,
1800, 90.00, 25.00, 407000,
2700, 135.00, 15.00, 409000,
3600, 180.00, 5.00, 408000
]
},
"path": {
"material": {
"solidColor": {
"color": { "rgba": [0, 255, 255, 128] }
}
},
"width": 2,
"leadTime": 3600,
"trailTime": 3600,
"resolution": 120
}
}
];
// Caricare il CZML nel viewer
const dataSource = await Cesium.CzmlDataSource.load(czml);
viewer.dataSources.add(dataSource);
// Seguire il satellite
viewer.trackedEntity = dataSource.entities.getById('satellite-1');
✅ Risultato: Un satellite animato in orbita con la sua traiettoria visibile, caricato interamente da un documento JSON dichiarativo. Perfetto per dati generati da backend o API esterne.
Sezione 12: GeoJSON e KML — Importare Dati Vettoriali Standard
Scenario: Hai dati geospaziali esistenti in formato GeoJSON o KML e vuoi visualizzarli sul globo 3D.
// Caricare un file GeoJSON
const geoJsonData = await Cesium.GeoJsonDataSource.load(
'/data/regioni-italia.geojson',
{
stroke: Cesium.Color.BLUE,
fill: Cesium.Color.BLUE.withAlpha(0.2),
strokeWidth: 2,
clampToGround: true
}
);
viewer.dataSources.add(geoJsonData);
viewer.zoomTo(geoJsonData);
// Personalizzare le entità dopo il caricamento
const entities = geoJsonData.entities.values;
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
const name = entity.name;
// Colorare ogni regione in base a una proprietà
if (entity.polygon) {
entity.polygon.material = Cesium.Color.fromRandom({
alpha: 0.4
});
entity.polygon.outline = true;
entity.polygon.outlineColor = Cesium.Color.WHITE;
}
}
// Caricare un file KML
const kmlData = await Cesium.KmlDataSource.load(
'/data/luoghi-interesse.kml',
{
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
clampToGround: true
}
);
viewer.dataSources.add(kmlData);
✅ Risultato: Dati vettoriali standard importati e visualizzati sul globo 3D con personalizzazione completa di colori, stili e interattività.
Sezione 13: Interazione Utente — Click, Hover e Selezione
Scenario: Vuoi che l'utente possa cliccare su entità e 3D Tiles per ottenere informazioni, o che la mappa reagisca al passaggio del mouse.
// Gestire il click su entità
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((click) => {
// Identificare l'oggetto cliccato
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
// Se è un'entità
if (pickedObject.id && pickedObject.id instanceof Cesium.Entity) {
const entity = pickedObject.id;
console.log('Entità cliccata:', entity.name);
alert(`Hai cliccato su: ${entity.name}`);
}
// Se è un 3D Tile
if (pickedObject instanceof Cesium.Cesium3DTileFeature) {
const feature = pickedObject;
const name = feature.getProperty('name');
const height = feature.getProperty('height');
console.log(`Edificio: ${name}, Altezza: ${height}m`);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// Gestire l'hover (passaggio del mouse)
handler.setInputAction((movement) => {
const pickedObject = viewer.scene.pick(movement.endPosition);
if (Cesium.defined(pickedObject) &&
pickedObject instanceof Cesium.Cesium3DTileFeature) {
// Evidenziare l'edificio sotto il mouse
pickedObject.color = Cesium.Color.YELLOW.withAlpha(0.5);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Ottenere le coordinate geografiche dal click
handler.setInputAction((click) => {
const cartesian = viewer.camera.pickEllipsoid(
click.position,
viewer.scene.globe.ellipsoid
);
if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
console.log(`Coordinate: ${lat.toFixed(6)}, ${lon.toFixed(6)}`);
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
✅ Risultato: Un'interfaccia interattiva dove l'utente può esplorare il globo e ottenere informazioni dettagliate cliccando su entità e oggetti 3D.
Sezione 14: Controllo della Camera — Volo, Animazione, Tracking
Scenario: Vuoi controllare programmaticamente la camera per creare flythrough cinematici, seguire entità in movimento o limitare la navigazione a un'area specifica.
// Volo animato verso una destinazione
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 500),
orientation: {
heading: Cesium.Math.toRadians(20.0),
pitch: Cesium.Math.toRadians(-30.0),
roll: 0.0
},
duration: 3, // durata in secondi
complete: () => {
console.log('Volo completato!');
}
});
// Posizionamento istantaneo della camera (senza animazione)
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(9.1900, 45.4642, 2000),
orientation: {
heading: 0.0,
pitch: Cesium.Math.toRadians(-45.0),
roll: 0.0
}
});
// Guardare un punto specifico
viewer.camera.lookAt(
Cesium.Cartesian3.fromDegrees(12.4924, 41.8902, 0), // Colosseo
new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(45), // heading
Cesium.Math.toRadians(-30), // pitch
500 // distanza in metri
)
);
// Limitare l'area di navigazione
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 100;
viewer.scene.screenSpaceCameraController.maximumZoomDistance = 50000;
// Tour automatico con più tappe
async function tourItalia() {
const tappe = [
{ lon: 12.4964, lat: 41.9028, alt: 800, nome: 'Roma' },
{ lon: 11.2558, lat: 43.7696, alt: 600, nome: 'Firenze' },
{ lon: 12.3155, lat: 45.4408, alt: 500, nome: 'Venezia' },
{ lon: 9.1900, lat: 45.4642, alt: 700, nome: 'Milano' },
];
for (const tappa of tappe) {
await new Promise((resolve) => {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
tappa.lon, tappa.lat, tappa.alt
),
orientation: {
heading: 0,
pitch: Cesium.Math.toRadians(-25.0),
},
duration: 2,
complete: resolve
});
});
// Pausa di 3 secondi ad ogni tappa
await new Promise(r => setTimeout(r, 3000));
}
}
tourItalia();
✅ Risultato: Tour cinematici automatizzati, tracking di entità in movimento e navigazione controllata per esperienze utente guidate e immersive.
Sezione 15: Integrazione con React
Scenario: Stai sviluppando un'applicazione React e vuoi integrare un globo CesiumJS come componente riutilizzabile.
// CesiumGlobe.jsx — Componente React per CesiumJS
import React, { useEffect, useRef } from 'react';
import {
Viewer,
Terrain,
Ion,
Cartesian3,
Math as CesiumMath,
createOsmBuildingsAsync
} from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
Ion.defaultAccessToken = 'IL_TUO_ACCESS_TOKEN';
export default function CesiumGlobe({ lat = 41.9028, lon = 12.4964, height = 800 }) {
const containerRef = useRef(null);
const viewerRef = useRef(null);
useEffect(() => {
if (!containerRef.current) return;
// Crea il viewer
const viewer = new Viewer(containerRef.current, {
terrain: Terrain.fromWorldTerrain(),
animation: false,
timeline: false,
});
viewerRef.current = viewer;
// Vola alla posizione iniziale
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(lon, lat, height),
orientation: {
heading: CesiumMath.toRadians(0),
pitch: CesiumMath.toRadians(-20),
}
});
// Aggiungi edifici
createOsmBuildingsAsync().then((tileset) => {
viewer.scene.primitives.add(tileset);
});
// Cleanup al dismount
return () => {
if (viewerRef.current && !viewerRef.current.isDestroyed()) {
viewerRef.current.destroy();
}
};
}, [lat, lon, height]);
return (
<div
ref={containerRef}
style={{ width: '100%', height: '100vh' }}
/>
);
}
// App.jsx — Utilizzo del componente
import CesiumGlobe from './CesiumGlobe';
function App() {
return (
<div>
<h1>La Mia App Geospaziale</h1>
<CesiumGlobe lat={41.9028} lon={12.4964} height={1000} />
</div>
);
}
export default App;
✅ Risultato: Un componente React riutilizzabile che incapsula CesiumJS, con gestione corretta del ciclo di vita e cleanup delle risorse.
Sezione 16: Analisi Geospaziale — Misurazioni e Calcoli
Scenario: Vuoi calcolare distanze, aree e altitudini direttamente nel browser per analisi geospaziali.
// Calcolare la distanza tra due punti
const point1 = Cesium.Cartographic.fromDegrees(12.4964, 41.9028); // Roma
const point2 = Cesium.Cartographic.fromDegrees(2.3522, 48.8566); // Parigi
const geodesic = new Cesium.EllipsoidGeodesic(point1, point2);
const distanzaMetri = geodesic.surfaceDistance;
const distanzaKm = distanzaMetri / 1000;
console.log(`Distanza Roma-Parigi: ${distanzaKm.toFixed(2)} km`);
// Ottenere l'altitudine del terreno in un punto
const positions = [Cesium.Cartographic.fromDegrees(12.4964, 41.9028)];
const updatedPositions = await Cesium.sampleTerrainMostDetailed(
viewer.terrainProvider,
positions
);
console.log(`Altitudine a Roma: ${updatedPositions[0].height.toFixed(2)} m`);
// Calcolare l'area di un poligono
function calcolaArea(degreesArray) {
const positions = [];
for (let i = 0; i < degreesArray.length; i += 2) {
positions.push(Cesium.Cartographic.fromDegrees(
degreesArray[i],
degreesArray[i + 1]
));
}
// Usa il metodo di Cesium per il calcolo dell'area sferica
const cartesianPositions = positions.map(p =>
Cesium.Cartesian3.fromRadians(p.longitude, p.latitude)
);
// Area in metri quadrati
const area = Cesium.PolygonPipeline.computeArea2D(
cartesianPositions.map(p => {
const carto = Cesium.Cartographic.fromCartesian(p);
return new Cesium.Cartesian2(carto.longitude, carto.latitude);
})
);
const R = 6371000; // raggio terrestre in metri
return Math.abs(area) * R * R;
}
✅ Risultato: Strumenti di analisi geospaziale direttamente nel browser, senza dipendenze da server GIS esterni.
Sezione 17: Performance e Ottimizzazione
Scenario: La tua applicazione CesiumJS deve funzionare bene anche su dispositivi meno potenti o con grandi quantità di dati.
// Ottimizzazione del rendering
viewer.scene.globe.enableLighting = true;
viewer.scene.globe.maximumScreenSpaceError = 2; // qualità (minore = migliore)
viewer.scene.globe.tileCacheSize = 100;
// Limitare il frame rate per risparmiare batteria/CPU
viewer.targetFrameRate = 30; // 30 fps invece di 60
// Request render mode: renderizza solo quando cambia qualcosa
viewer.requestRenderMode = true;
viewer.maximumRenderTimeChange = Infinity;
// Ottimizzazione dei 3D Tiles
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188);
tileset.maximumScreenSpaceError = 16; // Più alto = meno dettaglio
tileset.maximumMemoryUsage = 256; // Limite memoria in MB
tileset.dynamicScreenSpaceError = true;
tileset.dynamicScreenSpaceErrorDensity = 0.00278;
tileset.dynamicScreenSpaceErrorFactor = 4.0;
tileset.skipLevelOfDetail = true;
tileset.immediatelyLoadDesiredLevelOfDetail = false;
tileset.loadSiblings = false;
viewer.scene.primitives.add(tileset);
// Frustum culling e occlusione
viewer.scene.globe.depthTestAgainstTerrain = true;
// Monitoraggio delle performance
viewer.scene.debugShowFramesPerSecond = true; // Mostra FPS
// Rimuovere entità non più necessarie
viewer.entities.removeAll();
// Distruggere il viewer quando non serve più
// viewer.destroy();
✅ Risultato: Un'applicazione ottimizzata che funziona fluidamente anche con grandi dataset, grazie al controllo preciso di rendering, memoria e livello di dettaglio.
Sezione 18: Casi d'Uso nel Mondo Reale
Aerospazio e Difesa: CesiumJS viene utilizzato per la visualizzazione di orbite satellitari, il monitoraggio di detriti spaziali e la pianificazione di missioni. La capacità nativa di gestire dati time-dynamic lo rende ideale per il tracking in tempo reale e le simulazioni. Organizzazioni come la NASA e l'ESA utilizzano CesiumJS nelle loro piattaforme di visualizzazione.
Pianificazione Urbana e Smart City: Le amministrazioni comunali usano CesiumJS per visualizzare progetti infrastrutturali in contesto, simulare la crescita urbana e pianificare reti di trasporto. La possibilità di sovrapporre modelli BIM a gemelli digitali delle città esistenti permette di valutare l'impatto visivo e strutturale di nuove costruzioni prima ancora che vengano realizzate.
Droni e Mappatura: CesiumJS è lo strumento di visualizzazione ideale per modelli fotogrammetrici generati da rilevamenti aerei. Le nuvole di punti LiDAR e i mesh 3D prodotti dai software di elaborazione possono essere convertiti in 3D Tiles e visualizzati in modo fluido nel browser.
Energia e Risorse Naturali: Nel settore energetico viene impiegato per la visualizzazione di dati geologici sotterranei, la pianificazione di parchi eolici, il monitoraggio di pipeline e il tracciamento di asset distribuiti sul territorio.
Guida Autonoma e Mobilità: Le aziende nel settore della guida autonoma utilizzano CesiumJS per visualizzare i dati raccolti dai sensori dei veicoli (LiDAR, radar, telecamere) nel contesto geospaziale reale, facilitando il debug, l'analisi e la validazione degli algoritmi di navigazione.
Sezione 19: Best Practice e Consigli
- Usa sempre il request render mode in applicazioni dove il globo
non cambia continuamente: risparmia CPU e batteria impostando
viewer.requestRenderMode = true. - Gestisci il ciclo di vita del Viewer: chiama
viewer.destroy()quando il componente viene smontato per liberare le risorse GPU. - Preferisci le Primitive alle Entity per grandi quantità di oggetti:
l'API Entity è più semplice ma meno performante. Per migliaia di geometrie, usa
PrimitiveCollection. - Limita la memoria dei 3D Tiles: imposta
maximumMemoryUsageper evitare che il browser esaurisca la memoria su dispositivi con risorse limitate. - Usa il depth test: abilita
depthTestAgainstTerrainper evitare che le entità appaiano attraverso le montagne. - Configura CESIUM_BASE_URL correttamente: un errore comune è dimenticare di servire i file statici di CesiumJS (Workers, Assets) o impostare un percorso base errato.
Sezione 20: Risorse e Community
- Sito ufficiale: cesium.com
- GitHub: github.com/CesiumGS/cesium
- Sandcastle: sandcastle.cesium.com — Editor live con decine di esempi
- Community Forum: community.cesium.com
- Documentazione API: cesium.com/learn/cesiumjs/ref-doc
- Learning Center: cesium.com/learn
Conclusione
CesiumJS rappresenta lo stato dell'arte nella visualizzazione geospaziale 3D per il web. La combinazione di un motore di rendering potente, il supporto per standard aperti come 3D Tiles e glTF, la capacità di gestire dataset massivi tramite streaming progressivo e il supporto nativo per la dimensione temporale lo rendono uno strumento unico nel suo genere. Che tu stia costruendo un sistema di monitoraggio satellitare, un gemello digitale urbano o un'applicazione di analisi ambientale, CesiumJS fornisce le fondamenta su cui costruire esperienze geospaziali 3D immersive direttamente nel browser.