Skip to content

Commit

Permalink
Update Cesium on add/remove layers collection
Browse files Browse the repository at this point in the history
- Add listeners for when layers are added or removed from the MapAsset
  collection and update the layers rendered on the Cesium map and the layers
  displayed in the layer list.

Issue #2180, #1923, #1775
  • Loading branch information
robyngit committed Aug 24, 2023
1 parent 76f40f0 commit ddb9543
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 33 deletions.
2 changes: 0 additions & 2 deletions src/js/models/connectors/Map-Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,6 @@ define([
* See {@link MapSearchFiltersConnector#onMoveEnd}
*/
onMoveEnd: function () {
const searchResults = this.get("searchResults");
const map = this.get("map");
this.showGeoHashLayer();
this.updateFacet();
},
Expand Down
21 changes: 18 additions & 3 deletions src/js/models/maps/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,16 +351,31 @@ define([
* Add a layer or other asset to the map. This is the best way to add a
* layer to the map because it will ensure that this map model is set on
* the layer model.
* @param {Object | MapAsset} layer - A map asset model or object with
* @todo Enable adding a terrain asset.
* @param {Object | MapAsset} asset - A map asset model or object with
* attributes to set on a new map asset model.
* @returns {MapAsset} The new layer model.
* @since 2.25.0
*/
addAsset: function (layer) {
addAsset: function (asset) {
const layers = this.get("layers") || this.resetLayers();
return layers.addAsset(layer, this);
return layers.addAsset(asset, this);
},

/**
* Remove a layer from the map.
* @param {MapAsset} asset - The layer model to remove from the map.
* @since x.x.x
*/
removeAsset: function (asset) {
if(!asset) return;
const layers = this.get("layers");
if(!layers) return;
// Remove by ID because the model is passed directly. Not sure if this
// is a bug in the MapAssets collection or Backbone?
if (layers) layers.remove(asset.cid);
}

}
);

Expand Down
100 changes: 72 additions & 28 deletions src/js/views/maps/CesiumWidgetView.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,30 @@ define(
* @property {string} renderFunction The name of the function in the view that
* will add the asset to the map and render it, when passed the cesiumModel
* attribute from the MapAsset model
* @property {string} removeFunction The name of the function in the view that
* will remove the asset from the map, when passed the cesiumModel attribute from
* the MapAsset model
*/
mapAssetRenderFunctions: [
{
types: ['Cesium3DTileset'],
renderFunction: 'add3DTileset'
renderFunction: 'add3DTileset',
removeFunction: 'remove3DTileset'
},
{
types: ['GeoJsonDataSource', 'CzmlDataSource'],
renderFunction: 'addVectorData'
renderFunction: 'addVectorData',
removeFunction: 'removeVectorData'
},
{
types: ['BingMapsImageryProvider', 'IonImageryProvider', 'TileMapServiceImageryProvider', 'WebMapTileServiceImageryProvider', 'WebMapServiceImageryProvider', 'OpenStreetMapImageryProvider'],
renderFunction: 'addImagery'
renderFunction: 'addImagery',
removeFunction: 'removeImagery'
},
{
types: ['CesiumTerrainProvider'],
renderFunction: 'updateTerrain'
renderFunction: 'updateTerrain',
removeFunction: null
}
],

Expand Down Expand Up @@ -194,7 +201,6 @@ define(
// raised.
view.camera.percentChanged = 0.1


// Disable HDR lighting for better performance and to avoid changing imagery colors.
view.scene.highDynamicRange = false;
view.scene.globe.enableLighting = false;
Expand Down Expand Up @@ -251,6 +257,14 @@ define(

const view = this;

// Listen for addition or removal of layers
// TODO: Add similar listeners for terrain
const layers = view.model.get('layers')
view.stopListening(layers, 'add');
view.listenTo(layers, 'add', view.addAsset);
view.stopListening(layers, 'remove');
view.listenTo(layers, 'remove', view.removeAsset);

// Zoom functions executed after each scene render
view.scene.postRender.addEventListener(function () {
view.postRender();
Expand Down Expand Up @@ -1156,10 +1170,10 @@ define(
* @since x.x.x
*/
addNewAsset: function (mapAsset) {
// TODO: Set a listener on the layers collection for add events, and
// call this function when a new layer is added
if(!mapAsset) return
const newAsset = this.model.addAsset(mapAsset);
this.addAsset(newAsset);
// The add event on the layers collection will trigger the addAsset
// function below, which will render the asset in the map
return newAsset
},

Expand Down Expand Up @@ -1227,27 +1241,25 @@ define(
},

/**
* Remove an asset (layer) from the map model and remove it from the map
* @param {MapAsset} mapAsset - The MapAsset model to remove from the map
* When an asset is removed from the map model, remove it from the map.
* @param {MapAsset} mapAsset - The MapAsset model removed from the map
* @since x.x.x
*/
removeAsset: function (mapAsset) {
// TODO: Set a listener on the layers collection for remove events, and
// call this function when a new layer is removed
try {
if (!mapAsset) {
return
}
// TODO: Implement this!
// this.model.removeAsset(mapAsset)
// Remove the layer from the map
// ...
}
catch (error) {
console.log(
'There was an error removing an asset from a CesiumWidgetView' +
'. Error details: ' + error
);
removeAsset: function (mapAsset, b, c) {
if (!mapAsset) return
// Get the cesium model from the asset
const cesiumModel = mapAsset.get('cesiumModel')
if (!cesiumModel) return
// Find the remove function for this type of asset
const removeFunctionName = this.mapAssetRenderFunctions.find(function (option) {
return option.types.includes(mapAsset.get('type'))
})?.removeFunction
const removeFunction = this[removeFunctionName]
// If there is a function for this type of asset, call it
if (removeFunction && typeof removeFunction === 'function') {
removeFunction.call(this, cesiumModel)
} else {
console.log('No remove function found for this type of asset', mapAsset);
}
},

Expand All @@ -1272,6 +1284,16 @@ define(
this.scene.primitives.add(cesiumModel)
},

/**
* Remove a 3D tileset from the map.
* @param {Cesium.Cesium3DTileset} cesiumModel The Cesium 3D tileset model to
* remove from the map
* @since x.x.x
*/
remove3DTileset: function (cesiumModel) {
this.scene.primitives.remove(cesiumModel)
},

/**
* Renders vector data (excluding 3D tilesets) in the Map.
* @param {Cesium.GeoJsonDataSource} cesiumModel - The Cesium data source
Expand All @@ -1281,6 +1303,16 @@ define(
this.dataSourceCollection.add(cesiumModel)
},

/**
* Remove vector data (excluding 3D tilesets) from the Map.
* @param {Cesium.GeoJsonDataSource} cesiumModel - The Cesium data source
* model to remove from the map
* @since x.x.x
*/
removeVectorData: function (cesiumModel) {
this.dataSourceCollection.remove(cesiumModel)
},

/**
* Renders imagery in the Map.
* @param {Cesium.ImageryLayer} cesiumModel The Cesium imagery model to render
Expand All @@ -1290,12 +1322,24 @@ define(
this.sortImagery()
},

/**
* Remove imagery from the Map.
* @param {Cesium.ImageryLayer} cesiumModel The Cesium imagery model to remove
* from the map
* @since x.x.x
*/
removeImagery: function (cesiumModel) {
console.log('Removing imagery from map', cesiumModel);
console.log('Imagery layers', this.scene.imageryLayers);
this.scene.imageryLayers.remove(cesiumModel)
},

/**
* Arranges the imagery that is rendered the Map according to the order
* that the imagery is arranged in the layers collection.
* @since 2.21.0
*/
sortImagery() {
sortImagery: function() {
try {
const imageryInMap = this.scene.imageryLayers
const imageryModels = this.model.get('layers').getAll('CesiumImagery')
Expand Down
30 changes: 30 additions & 0 deletions src/js/views/maps/LayerListView.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,42 @@ define(
this[key] = value;
}
}
this.setListeners();
} catch (e) {
console.log('A LayerListView failed to initialize. Error message: ' + e);
}

},

/**
* Remove any event listeners on the collection
* @since x.x.x
*/
removeListeners: function () {
try {
if (this.collection) {
this.stopListening(this.collection);
}
} catch (e) {
console.log('Failed to remove listeners:', e);
}
},

/**
* Add or remove items from the list when the collection changes
* @since x.x.x
*/
setListeners: function () {
try {
if (this.collection) {
this.listenTo(this.collection, 'add', this.render);
this.listenTo(this.collection, 'remove', this.render);
}
} catch (e) {
console.log('Failed to set listeners:', e);
}
},

/**
* Renders this view
* @return {LayerListView} Returns the rendered view element
Expand Down

0 comments on commit ddb9543

Please sign in to comment.