🇮🇹 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.
🇦🇱 Cesium.js — Udhëzues i Plotë për Vizualizimin Gjeohapësinor 3D në Web
Hyrje: Bota në 3D në Shfletuesin Tënd
Imagjino të eksplorosh një model tredimensional të gjithë planetit Tokë drejtpërdrejt nga shfletuesi, pa instaluar asnjë shtojcë. Të fluturosh mbi qytete me ndërtesa 3D fotorealistike, të analizosh terrenin malor me saktësi centimetrike, ose të gjurmosh në kohë reale fluturimin e një aeroplani nga San Francisko në Kopenhagë. E gjithë kjo është e mundur falë CesiumJS, bibliotekës JavaScript me burim të hapur që ka ridefinuar vizualizimin gjeohapësinor në web.
CesiumJS është shumë më tepër se një bibliotekë e thjeshtë hartash: është një motor i vërtetë 3D gjeohapësinor i projektuar për të ofruar performancë të lartë, saktësi shkencore dhe cilësi vizuale të nivelit profesional. Që nga lindja e tij në vitin 2012, është bërë standardi de facto për ata që kanë nevojë të vizualizojnë të dhëna gjeohapësinore tredimensionale në fusha që shkojnë nga hapësira ajrore te planifikimi urban, nga mbrojtja te menaxhimi i dronëve.
Në këtë udhëzues të plotë do të eksplorojmë çdo aspekt të CesiumJS: nga arkitektura e brendshme te funksionalitetet kryesore, nga konfigurimi fillestar te shembujt e avancuar, deri te rastet e përdorimit real që demonstrojnë fuqinë e kësaj biblioteke.
Seksioni 1: Çfarë Është CesiumJS dhe Pse Është i Rëndësishëm
CesiumJS është një bibliotekë JavaScript e lëshuar nën licencën Apache 2.0, pra plotësisht falas si për përdorim tregtar ashtu edhe jo-tregtar. Përdor WebGL për përshpejtimin harduerik të grafikës, që do të thotë se çdo shfletues modern mund të renderojë globra 3D komplekse pa varësi të jashtme.
Thelbi i filozofisë së Cesium është ndërveprueshëmeria bazuar në standarde të hapura. Në vend që të krijojë formate pronësore, ekipi i Cesium ka zhvilluar dhe promovuar specifika të hapura si 3D Tiles (tani standard OGC) dhe mbështetet në formate të konsoliduara si glTF, KML, GeoJSON dhe CZML.
Arkitektura është menduar për të menaxhuar grupe masive të dhënash përmes transmetimit progresiv: në vend që të ngarkojë modele të tëra në memorie, CesiumJS ngarkon dinamikisht vetëm pjesët e të dhënave të dukshme për përdoruesin, duke përshtatur nivelin e detajit bazuar në distancën e kamerës.
// Shembull minimal: krijimi i një globi CesiumJS
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
// Kjo është e gjitha që nevojitet për të pasur një glob 3D interaktiv!
Me vetëm tre rreshta kodi ke një glob tokësor 3D interaktiv me terren me rezolucion të lartë, navigim me maus dhe prekje, dhe akses në widget-et e integruara të CesiumJS.
Seksioni 2: Ekosistemi Cesium — CesiumJS dhe Cesium ion
Është thelbësore të dallojmë mes dy komponentëve kryesore të ekosistemit Cesium, sepse luajnë role plotësuese por të dallueshme.
CesiumJS është motori i renderimit në anën e klientit: biblioteka JavaScript që merret me vizatimin e globit, menaxhimin e kamerës, renderimin e tile-ve 3D dhe menaxhimin e ndërveprimit të përdoruesit. Është plotësisht me burim të hapur.
Cesium ion është platforma cloud (SaaS) që merret me pritjen, optimizimin dhe shërbimin e të dhënave gjeohapësinore në formatin 3D Tiles. Kur krijon një llogari falas në Cesium ion, merr akses të menjëhershëm në përmbajtje globale të para-ngarkuara si:
- Cesium World Terrain — një model i lartësisë së terrenit me rezolucion të lartë që mbulon gjithë planetin.
- Cesium OSM Buildings — një shtresë globale e ndërtesave 3D e derivuar nga OpenStreetMap, me mbi 350 milion struktura.
- Bing Maps Imagery — imazhe satelitore me rezolucion të lartë.
// Konfiguro tokenin e aksesit në Cesium ion
Cesium.Ion.defaultAccessToken = 'TOKENI_YT_I_AKSESIT';
// Tokeni mundëson aksesin në përmbajtje globale:
// - Cesium World Terrain (asset ID: 1)
// - Cesium OSM Buildings (asset ID: 96188)
// - Bing Maps Aerial Imagery
// - Asetet tuaja personale të ngarkuara në ion
Seksioni 3: Konfigurimi me CDN — Mënyra Më e Shpejtë për të Filluar
Skenari: Dëshiron të krijosh shpejt një faqe HTML me një glob 3D interaktiv pa konfiguruar asnjë mjet ndërtimi.
<!DOCTYPE html>
<html lang="sq">
<head>
<meta charset="utf-8">
<title>Aplikacioni Im i Parë CesiumJS</title>
<!-- Përfshi CesiumJS nga CDN zyrtare -->
<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">
// Zëvendëso me tokenin tënd nga https://ion.cesium.com/tokens
Cesium.Ion.defaultAccessToken = 'TOKENI_YT_I_AKSESIT';
// Inicializo Viewer-in me terren botëror
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
// Flutura drejt Tiranës
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 800),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-20.0),
}
});
// Shto ndërtesa 3D globale (OpenStreetMap)
const buildings = await Cesium.createOsmBuildingsAsync();
viewer.scene.primitives.add(buildings);
</script>
</body>
</html>
✅ Rezultati: Duke hapur këtë skedar në shfletues do të shohësh globin tokësor duke fluturuar drejt Tiranës me ndërtesa 3D të dukshme. I gjithë skena është interaktive.
Seksioni 4: Konfigurimi me NPM — Për Projekte të Strukturuara
Skenari: Po ndërton një aplikacion web modern me një framework si React, Angular ose Vue, dhe përdor një module bundler si Webpack, Vite ose Rollup.
# Instalimi përmes npm
npm install cesium
# ose me yarn
yarn add cesium
# ose me pnpm
pnpm add cesium
// E RËNDËSISHME: CESIUM_BASE_URL duhet vendosur PARA importit
window.CESIUM_BASE_URL = '/';
import {
Cartesian3,
createOsmBuildingsAsync,
Ion,
Math as CesiumMath,
Terrain,
Viewer
} from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
// Konfiguro tokenin e aksesit
Ion.defaultAccessToken = 'TOKENI_YT_I_AKSESIT';
// Inicializo Viewer-in
const viewer = new Viewer('cesiumContainer', {
terrain: Terrain.fromWorldTerrain(),
});
// Flutura drejt Tiranës
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(19.8187, 41.3275, 800),
orientation: {
heading: CesiumMath.toRadians(0.0),
pitch: CesiumMath.toRadians(-20.0),
}
});
// Shto ndërtesa 3D
const buildings = await createOsmBuildingsAsync();
viewer.scene.primitives.add(buildings);
✅ Rezultati: Një konfigurim i pastër dhe modular, i përshtatshëm me tree-shaking dhe optimizim i bundle-it për prodhim.
Seksioni 5: Konfigurimi i Viewer-it — Opsione dhe Personalizim
Skenari: Dëshiron të personalizosh pamjen dhe sjelljen e globit: të fshehësh widget-e të panevojshme, të ndryshosh shtresën bazë të imazheve, të konfigurosh opsionet e renderimit.
// Viewer me konfigurim të plotë
const viewer = new Cesium.Viewer('cesiumContainer', {
// Terreni
terrain: Cesium.Terrain.fromWorldTerrain({
requestWaterMask: true,
requestVertexNormals: true
}),
// Widget-et UI
animation: false,
timeline: false,
fullscreenButton: true,
vrButton: false,
geocoder: true,
homeButton: true,
navigationHelpButton: false,
baseLayerPicker: true,
sceneModePicker: true,
// Renderimi
shadows: true,
shouldAnimate: true,
useBrowserRecommendedResolution: true,
});
// Personalizimi i atmosferës
viewer.scene.skyAtmosphere.show = true;
viewer.scene.fog.enabled = true;
viewer.scene.fog.density = 0.0002;
✅ Rezultati: Një viewer plotësisht i personalizuar me hije realiste, atmosferë, mjegull dhe widget-e të zgjedhura bazuar në nevojat e aplikacionit.
Seksioni 6: 3D Tiles — Standardi për Grupe Masive të Dhënash
Skenari: Ke një model fotogrametrik të një qyteti të tërë, një re pikash LiDAR me miliarda pika, ose një grup të dhënash me ndërtesa 3D. Dëshiron ta vizualizosh në shfletues në mënyrë të rrjedhshme.
// Ngarkimi i një tileset 3D Tiles nga Cesium ion
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188);
viewer.scene.primitives.add(tileset);
// Zmadhim automatik mbi tileset-in
viewer.zoomTo(tileset);
// Aplikimi i një stili kushtëzuar mbi 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"
});
// Ngarkimi i 3D Tiles nga një URL e personalizuar
const customTileset = await Cesium.Cesium3DTileset.fromUrl(
'https://serveri-im.com/tileset/tileset.json',
{
maximumScreenSpaceError: 16,
maximumMemoryUsage: 512,
dynamicScreenSpaceError: true,
skipLevelOfDetail: true
}
);
viewer.scene.primitives.add(customTileset);
✅ Rezultati: Grupe të dhënash me çdo madhësi të vizualizuara në mënyrë të rrjedhshme falë transmetimit progresiv.
Seksioni 7: Terreni dhe Shtresat e Imazheve
Skenari: Dëshiron të vizualizosh terrenin realistik të Tokës me male, lugina dhe fund-dete oqeanike, duke mbivendosur shtresa të ndryshme imazhesh satelitore.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain({
requestWaterMask: true,
requestVertexNormals: true
})
});
// Shtimi i një shtrese imazhesh të personalizuara
const imageryLayer = viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
minimumLevel: 0,
maximumLevel: 19,
credit: '© OpenStreetMap contributors'
})
);
// Rregullimi i transparencës së shtresës
imageryLayer.alpha = 0.7;
// Shtimi i një shtrese WMS
const wmsLayer = viewer.imageryLayers.addImageryProvider(
new Cesium.WebMapServiceImageryProvider({
url: 'https://ows.terrestris.de/osm/service',
layers: 'OSM-WMS',
parameters: {
transparent: true,
format: 'image/png'
}
})
);
✅ Rezultati: Një glob me terren realistik dhe shtresa të shumta imazhesh të mbivendosura, me kontroll të plotë mbi transparencën dhe renditjen e shtresave.
Seksioni 8: Entitete dhe Gjeometri — Shënues, Poligone, Vija
Skenari: Dëshiron të shtosh pika interesi, zona të kufizuara, rrugë dhe informacione të tjera gjeohapësinore në globin tënd 3D.
// Shtimi i një shënuesi me dritare informuese
viewer.entities.add({
name: 'Sheshi Skënderbej',
position: Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 0),
point: {
pixelSize: 12,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
},
label: {
text: 'Sheshi Skënderbej',
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>Sheshi Skënderbej</h3><p>Qendra e Tiranës.</p>'
});
// Vizatimi i një poligoni me ekstruzion 3D
viewer.entities.add({
name: 'Qendra e Tiranës',
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
19.810, 41.332,
19.830, 41.332,
19.830, 41.322,
19.810, 41.322
]),
material: Cesium.Color.BLUE.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.BLUE,
extrudedHeight: 50,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
});
// Vizatimi i një polilinje (rrugë)
viewer.entities.add({
name: 'Bulevardi Dëshmorët e Kombit',
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
19.8187, 41.3275,
19.8200, 41.3180,
]),
width: 4,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.2,
color: Cesium.Color.YELLOW
}),
clampToGround: true
}
});
✅ Rezultati: Një glob i pasur me informacione gjeohapësinore interaktive me shënues, zona, rrugë dhe forma 3D.
Seksioni 9: Modele 3D me glTF
Skenari: Dëshiron të pozicionosh një model 3D (një ndërtesë, një automjet, një dron) mbi glob me pozicion, orientim dhe shkallë precize.
// Ngarkimi i një modeli glTF nga URL
const modelEntity = viewer.entities.add({
name: 'Modeli 3D',
position: Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 50),
model: {
uri: '/models/building.glb',
minimumPixelSize: 64,
maximumScale: 20000,
silhouetteColor: Cesium.Color.YELLOW,
silhouetteSize: 2,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
}
});
// Modeli 3D me orientim specifik
const position = Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 100);
const heading = Cesium.Math.toRadians(45);
const pitch = Cesium.Math.toRadians(0);
const roll = Cesium.Math.toRadians(0);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
new Cesium.HeadingPitchRoll(heading, pitch, roll)
);
viewer.entities.add({
name: 'Aeroplan',
position: position,
orientation: orientation,
model: {
uri: '/models/airplane.glb',
minimumPixelSize: 64,
runAnimations: true
}
});
✅ Rezultati: Modele 3D të pozicionuara me saktësi gjeohapësinore, me mbështetje për animacione dhe materiale PBR.
Seksioni 10: Vizualizimi Time-Dynamic (4D)
Skenari: Dëshiron të vizualizosh të dhëna që ndryshojnë në kohë: rrugën e një sateliti, kursin e një fluturimi, përhapjen e një fenomeni meteorologjik.
// Krijimi i një entiteti që lëviz në kohë
const start = Cesium.JulianDate.fromIso8601('2025-01-01T00:00:00Z');
const stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate());
// Konfigurimi i orës
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;
// Krijimi i pozicionit që ndryshon në kohë
const positionProperty = new Cesium.SampledPositionProperty();
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 0, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 10000) // Tiranë
);
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 120, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(12.4964, 41.9028, 11000) // Romë
);
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 240, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(23.7275, 37.9838, 10500) // Athinë
);
positionProperty.addSample(
Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate()),
Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 10000) // Kthim në Tiranë
);
// Krijimi i entitetit në lëvizje
const airplane = viewer.entities.add({
name: 'Fluturimi Ballkanik',
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
}
});
// Ndjek entitetin me kamerë
viewer.trackedEntity = airplane;
✅ Rezultati: Një aeroplan i animuar që përshkon rrugën Tiranë → Romë → Athinë → Tiranë, me gjurmë dritëse dhe kamera që e ndjek automatikisht.
Seksioni 11: Formati CZML — Të Dhëna Gjeohapësinore Kohore në JSON
Skenari: Dëshiron të përshkruash skena komplekse me të dhëna time-dynamic në një format deklarativ JSON.
const czml = [
{
"id": "document",
"name": "Gjurmimi i Satelitit",
"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": "Stacioni Ndërkombëtar i Hapësirës",
"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, 19.81, 41.32, 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
}
}
];
// Ngarko CZML në viewer
const dataSource = await Cesium.CzmlDataSource.load(czml);
viewer.dataSources.add(dataSource);
viewer.trackedEntity = dataSource.entities.getById('satellite-1');
✅ Rezultati: Një satelit i animuar në orbitë me trajektoren e tij të dukshme, i ngarkuar tërësisht nga një dokument JSON deklarativ.
Seksioni 12: GeoJSON dhe KML — Importimi i të Dhënave Vektoriale
Skenari: Ke të dhëna gjeohapësinore ekzistuese në format GeoJSON ose KML dhe dëshiron t'i vizualizosh në globin 3D.
// Ngarkimi i një skedari GeoJSON
const geoJsonData = await Cesium.GeoJsonDataSource.load(
'/data/rajonet-shqiperise.geojson',
{
stroke: Cesium.Color.BLUE,
fill: Cesium.Color.BLUE.withAlpha(0.2),
strokeWidth: 2,
clampToGround: true
}
);
viewer.dataSources.add(geoJsonData);
viewer.zoomTo(geoJsonData);
// Ngarkimi i një skedari KML
const kmlData = await Cesium.KmlDataSource.load(
'/data/vendet-interesit.kml',
{
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
clampToGround: true
}
);
viewer.dataSources.add(kmlData);
✅ Rezultati: Të dhëna vektoriale standarde të importuara dhe vizualizuara në globin 3D me personalizim të plotë.
Seksioni 13: Ndërveprimi i Përdoruesit — Klikim, Hover dhe Përzgjedhje
Skenari: Dëshiron që përdoruesi të mund të klikojë mbi entitete dhe 3D Tiles për të marrë informacione.
// Menaxhimi i klikimit mbi entitete
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((click) => {
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
if (pickedObject.id && pickedObject.id instanceof Cesium.Entity) {
const entity = pickedObject.id;
console.log('Entiteti i klikuar:', entity.name);
alert(`Klikove mbi: ${entity.name}`);
}
if (pickedObject instanceof Cesium.Cesium3DTileFeature) {
const feature = pickedObject;
const name = feature.getProperty('name');
const height = feature.getProperty('height');
console.log(`Ndërtesa: ${name}, Lartësia: ${height}m`);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// Marrja e koordinatave gjeografike nga kliku
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(`Koordinatat: ${lat.toFixed(6)}, ${lon.toFixed(6)}`);
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
✅ Rezultati: Një ndërfaqe interaktive ku përdoruesi mund të eksplorojë globin dhe të marrë informacione të detajuara.
Seksioni 14: Kontrolli i Kamerës — Fluturim, Animacion, Ndjekje
Skenari: Dëshiron të kontrollosh programatikisht kamerën për të krijuar flythrough kinematike.
// Fluturim i animuar drejt një destinacioni
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(19.8187, 41.3275, 500),
orientation: {
heading: Cesium.Math.toRadians(20.0),
pitch: Cesium.Math.toRadians(-30.0),
roll: 0.0
},
duration: 3,
complete: () => {
console.log('Fluturimi përfundoi!');
}
});
// Tur automatik me disa ndalesa
async function turShqiperi() {
const ndalesa = [
{ lon: 19.8187, lat: 41.3275, alt: 800, emer: 'Tiranë' },
{ lon: 19.5033, lat: 40.4667, alt: 600, emer: 'Vlorë' },
{ lon: 20.0833, lat: 39.6247, alt: 500, emer: 'Gjirokastër' },
{ lon: 20.0689, lat: 40.0781, alt: 700, emer: 'Berat' },
];
for (const ndalese of ndalesa) {
await new Promise((resolve) => {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
ndalese.lon, ndalese.lat, ndalese.alt
),
orientation: {
heading: 0,
pitch: Cesium.Math.toRadians(-25.0),
},
duration: 2,
complete: resolve
});
});
await new Promise(r => setTimeout(r, 3000));
}
}
turShqiperi();
✅ Rezultati: Ture kinematike automatike, ndjekje e entiteteve në lëvizje dhe navigim i kontrolluar.
Seksioni 15: Integrimi me React
Skenari: Po zhvillon një aplikacion React dhe dëshiron të integrosh një glob CesiumJS si komponent i ripërdorshëm.
// CesiumGlobe.jsx — Komponenti React për 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 = 'TOKENI_YT_I_AKSESIT';
export default function CesiumGlobe({ lat = 41.3275, lon = 19.8187, height = 800 }) {
const containerRef = useRef(null);
const viewerRef = useRef(null);
useEffect(() => {
if (!containerRef.current) return;
const viewer = new Viewer(containerRef.current, {
terrain: Terrain.fromWorldTerrain(),
animation: false,
timeline: false,
});
viewerRef.current = viewer;
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(lon, lat, height),
orientation: {
heading: CesiumMath.toRadians(0),
pitch: CesiumMath.toRadians(-20),
}
});
createOsmBuildingsAsync().then((tileset) => {
viewer.scene.primitives.add(tileset);
});
return () => {
if (viewerRef.current && !viewerRef.current.isDestroyed()) {
viewerRef.current.destroy();
}
};
}, [lat, lon, height]);
return (
<div ref={containerRef} style={{ width: '100%', height: '100vh' }} />
);
}
✅ Rezultati: Një komponent React i ripërdorshëm që kapsulon CesiumJS, me menaxhim korrekt të ciklit të jetës.
Seksioni 16: Analiza Gjeohapësinore — Matje dhe Llogaritje
Skenari: Dëshiron të llogaritësh distanca, sipërfaqe dhe lartësi drejtpërdrejt në shfletues.
// Llogaritja e distancës mes dy pikave
const pika1 = Cesium.Cartographic.fromDegrees(19.8187, 41.3275); // Tiranë
const pika2 = Cesium.Cartographic.fromDegrees(12.4964, 41.9028); // Romë
const geodesic = new Cesium.EllipsoidGeodesic(pika1, pika2);
const distancaMetra = geodesic.surfaceDistance;
const distancaKm = distancaMetra / 1000;
console.log(`Distanca Tiranë-Romë: ${distancaKm.toFixed(2)} km`);
// Marrja e lartësisë së terrenit në një pikë
const pozicione = [Cesium.Cartographic.fromDegrees(19.8187, 41.3275)];
const pozicionePerditësuara = await Cesium.sampleTerrainMostDetailed(
viewer.terrainProvider,
pozicione
);
console.log(`Lartësia në Tiranë: ${pozicionePerditësuara[0].height.toFixed(2)} m`);
✅ Rezultati: Mjete analize gjeohapësinore drejtpërdrejt në shfletues, pa varësi nga serverë GIS të jashtëm.
Seksioni 17: Performanca dhe Optimizimi
Skenari: Aplikacioni yt CesiumJS duhet të funksionojë mirë edhe në pajisje më pak të fuqishme.
// Optimizimi i renderimit
viewer.scene.globe.enableLighting = true;
viewer.scene.globe.maximumScreenSpaceError = 2;
viewer.scene.globe.tileCacheSize = 100;
// Kufizimi i frame rate
viewer.targetFrameRate = 30;
// Request render mode: renderizo vetëm kur ndryshon diçka
viewer.requestRenderMode = true;
viewer.maximumRenderTimeChange = Infinity;
// Optimizimi i 3D Tiles
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188);
tileset.maximumScreenSpaceError = 16;
tileset.maximumMemoryUsage = 256;
tileset.dynamicScreenSpaceError = true;
tileset.skipLevelOfDetail = true;
viewer.scene.primitives.add(tileset);
// Monitorimi i performancës
viewer.scene.debugShowFramesPerSecond = true;
✅ Rezultati: Një aplikacion i optimizuar që funksionon në mënyrë të rrjedhshme edhe me grupe të mëdha të dhënash.
Seksioni 18: Rastet e Përdorimit në Botën Reale
Hapësira Ajrore dhe Mbrojtja: CesiumJS përdoret për vizualizimin e orbitave satelitore, monitorimin e mbeturinave hapësinore dhe planifikimin e misioneve. NASA dhe ESA e përdorin në platformat e tyre.
Planifikimi Urban dhe Qytete Inteligjente: Administrata komunale përdorin CesiumJS për të vizualizuar projekte infrastrukturore, simuluar rritjen urbane dhe planifikuar rrjete transporti.
Dronë dhe Hartëzim: CesiumJS është mjeti ideal për vizualizimin e modeleve fotogrametrike të gjeneruara nga rilevime ajrore.
Energjia dhe Burimet Natyrore: Përdoret për vizualizimin e të dhënave gjeologjike nëntokësore dhe planifikimin e parkeve të erës.
Seksioni 19: Praktika Më të Mira dhe Këshilla
- Përdor gjithmonë request render mode në aplikacione ku globi
nuk ndryshon vazhdimisht:
viewer.requestRenderMode = true. - Menaxho ciklin e jetës së Viewer-it: thirr
viewer.destroy()kur komponenti çmontohet për të liruar burimet GPU. - Prefero Primitive-t mbi Entity për sasi të mëdha objektesh: API Entity është më e thjeshtë por më pak performante.
- Kufizo memorien e 3D Tiles: vendos
maximumMemoryUsagepër të shmangur shterimin e memorisë. - Përdor depth test: aktivo
depthTestAgainstTerrainpër të shmangur që entitetet të shfaqen përmes maleve. - Konfiguro CESIUM_BASE_URL saktë: një gabim i zakonshëm është të harrohet servimi i skedarëve statikë të CesiumJS.
Seksioni 20: Burime dhe Komuniteti
- Faqja zyrtare: cesium.com
- GitHub: github.com/CesiumGS/cesium
- Sandcastle: sandcastle.cesium.com
- Forumi i Komunitetit: community.cesium.com
- Dokumentimi API: cesium.com/learn/cesiumjs/ref-doc
- Qendra e Mësimit: cesium.com/learn
Përfundim
CesiumJS përfaqëson gjendjen e artit në vizualizimin gjeohapësinor 3D për web-in. Kombinimi i një motori të fuqishëm renderimi, mbështetja për standarde të hapura si 3D Tiles dhe glTF, aftësia për të menaxhuar grupe masive të dhënash përmes transmetimit progresiv dhe mbështetja vendase për dimensionin kohor e bëjnë një mjet unik në llojin e tij. Qoftë duke ndërtuar një sistem monitorimi satelitor, një binjak digjital urban ose një aplikacion analize mjedisore, CesiumJS ofron themelet mbi të cilat mund të ndërtosh përvoja gjeohapësinore 3D imersive drejtpërdrejt në shfletues.