Using CesiumWidget to display a GeoJSON

I’m struggling to use the CesiumWidget for display something simple as a GeoJSON source.

The only clear guide I found is this old discussion at GeoJSON datasource with Cesium widget, but replicating the same example (and fixing many API changes happened meanwhile) seems to not work anymore.

This is my code:

const osm = new Cesium.OpenStreetMapImageryProvider({
  url: "https://a.tile.openstreetmap.org/"
});
const widget = new Cesium.CesiumWidget("container", {
  skyBox: false,
  baseLayer: Cesium.ImageryLayer.fromProviderAsync(osm),
  baseLayerPicker: false,
  geocoder: false,
  creditContainer: document.createElement("none")
});

async function main() {
  const dataSourceCollection = new Cesium.DataSourceCollection();
  const datasource = new Cesium.GeoJsonDataSource();

  const jsonURL =
    "https://planetarycomputer.microsoft.com/api/stac/v1/collections/sentinel-2-l2a/items/S2B_MSIL2A_20240305T090739_R050_T42XWL_20240305T110543";
  // const jsonURL = "https://sandcastle.cesium.com/SampleData/ne_10m_us_states.topojson";

  const loaded = await datasource.load(jsonURL, {
    stroke: Cesium.Color.HOTPINK,
    fill: Cesium.Color.PINK,
    strokeWidth: 5,
    markerSymbol: "?"
  });

  dataSourceCollection.add(loaded);
  
  const dataSourceDisplay = new Cesium.DataSourceDisplay({
    scene: widget.scene,
    dataSourceCollection: dataSourceCollection
  });

  widget.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(68, 76, 500000)
  });

  /*
  const center = Cesium.Cartesian3.fromDegrees(68, 76, 250000);
  const heading = Cesium.Math.toRadians(20.0);
  const pitch = Cesium.Math.toRadians(-30.0);
  const range = 15000.0;
  widget.camera.lookAt(
    center,
    new Cesium.HeadingPitchRange(heading, pitch, range)
  );
  */

  const ready = dataSourceDisplay.update(new Cesium.JulianDate());
  console.log(ready);
}

main();

Globe is rendered correctly, camera moved at proper position, and no error in the console. But the Geojson is not rendered.

If I switch to Cesium.Viewer and I perform the minimal API changes required (no use of dataSourceCollection but directly using widget.dataSources.add), everything works as expected.

And this also trigger a question: what is the difference between Viewer and CesiumWidget?

Thanks for the question @keul

You need to continually update the data source display every frame not just once. You can hook into the widget’s clock to do that like below. (Matt also mentioned this in the thread you linked). See an updated version of your code working in Sandcastle here

widget.clock.onTick.addEventListener(function(clock){
  dataSourceDisplay.update(clock.currentTime);
});

The Viewer is an extra wrapper for the CesiumWidget class that includes the other widgets we provide (like timeline and animation clock etc) as well as sets up a simpler api and event handlers like that onTick for you.

My dumb! Thanks @jjspace
I suspect a bit more documentation on API page could help on this!

So, there is not real benefit on using Viewer instead of CesiumWidget and disabling what you don’t need (apart probably performance)?

So, there is not real benefit on using Viewer instead of CesiumWidget and disabling what you don’t need (apart probably performance)?

If you’re not using any of the addition widgets, using CesiumWidget only will bring in fewer dependencies. Depending on your build system and config, it can make your app smaller, and therefore faster to load.

1 Like

Late follow up to this @keul but I wanted to let you know that v1.123 was released last week. This release included a change to move the entity/dataSource functionality from the Viewer into the CesiumWidget. This change should hopefully make the scenario you were trying to do here a bit more seemless.

1 Like