From 55e4fe6d37271486473031b45c3dbf90b97fcae7 Mon Sep 17 00:00:00 2001 From: Lucas Angermann <75566260+lucas-angermann@users.noreply.github.com> Date: Wed, 10 Jul 2024 16:33:54 +0200 Subject: [PATCH] Map cesium update (#235) * feat: adding popup functionality. * feat: changing scene options * feat: adjusting popup style. * feat: update demo maps. * feat: adding globe color option. * feat: adding icon support for geojson features. * docs: updating changelog and readme. --- CHANGELOG.md | 9 ++ .../route-example-cesium.component.ts | 110 +++++++++++++++++- .../demo-maps/src/assets/icons/icon-72x72.png | Bin 0 -> 5258 bytes projects/map-cesium/README.md | 9 +- .../src/lib/map-cesium.component.html | 10 +- .../src/lib/map-cesium.component.scss | 58 ++++++++- .../src/lib/map-cesium.component.ts | 59 ++++++++-- .../src/lib/map-cesium.service.spec.ts | 15 +-- .../map-cesium/src/lib/map-cesium.service.ts | 52 ++++++++- 9 files changed, 287 insertions(+), 35 deletions(-) create mode 100644 projects/demo-maps/src/assets/icons/icon-72x72.png diff --git a/CHANGELOG.md b/CHANGELOG.md index c0b69b8af..6b141d4b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [13.X.X](https://github.com/dlr-eoc/ukis-frontend-libraries/tree/v13.X.X) (2024-07-10) (map-cesium) + +### Features +* **@dlr-eoc/map-cesium:** +- Added popup interface as an alternative to the infoBox. (In the long run the popup will replace the infoBox) +- Adjustments for 3D scene lighting and support for imageBasedLighting luminanceAtZenith. +- Added control option for the default globe color. +- Added support for icon markers for point geojson features. + # [13.0.0](https://github.com/dlr-eoc/ukis-frontend-libraries/tree/v13.0.0) (2024-07-08) (services-map-state, map-ol, map-cesium and map-maplibre) ### Breaking Changes diff --git a/projects/demo-maps/src/app/route-components/route-example-cesium/route-example-cesium.component.ts b/projects/demo-maps/src/app/route-components/route-example-cesium/route-example-cesium.component.ts index 830b81651..40d6bf795 100644 --- a/projects/demo-maps/src/app/route-components/route-example-cesium/route-example-cesium.component.ts +++ b/projects/demo-maps/src/app/route-components/route-example-cesium/route-example-cesium.component.ts @@ -51,10 +51,14 @@ export class RouteExampleCesiumComponent implements OnInit, OnDestroy { public mapStateSvc: MapStateService, public mapCesiumSvc: MapCesiumService ) { - this.controls = { + /* this.controls = { infoBox: true, selectionIndicator: true - } + } */ + this.controls = { + enablePopups: true, + globeColor: '#00FF00' + } } ngOnInit() { @@ -77,6 +81,18 @@ export class RouteExampleCesiumComponent implements OnInit, OnDestroy { addBaselayers() { const layers = [ + new VectorLayer({ + name: 'Transparent background', + id: 'blank', + type: 'geojson', + data: { + "type": "Feature", + "geometry": null, + }, + description: 'This is a transparent background. Use this to save bandwidth when no background map is needed.', + visible: false, + opacity: 0 + }), new OsmTileLayer({ visible: true }), @@ -234,7 +250,95 @@ export class RouteExampleCesiumComponent implements OnInit, OnDestroy { }, clampToGround: false } - }) + }), + new VectorLayer({ + id: 'geojson_test3', + name: 'GeoJSON Vector Layer (icons)', + attribution: `© DLR GeoJSON`, + type: 'geojson', + data: { + "type": "FeatureCollection", + "features": [ + { + type: "Feature", + properties: { + id: 1, + title: "Point 1", + iconUrl: './assets/icons/icon-72x72.png' + }, + geometry: { + coordinates: [ + 11.617674411393523, + 48.12108785075742 + ], + type: "Point" + } + }, + { + type: "Feature", + properties: { + id: 1, + title: "Point 1", + iconUrl: './assets/icons/icon-72x72.png' + }, + geometry: { + coordinates: [ + -73.98871110194915, + 40.704468034225556 + ], + type: "Point" + } + }, + { + type: "Feature", + properties: { + id: 1, + title: "Point 1", + iconUrl: './assets/icons/icon-72x72.png' + }, + geometry: { + coordinates: [ + -46.62002667427379, + -23.556899526881907 + ], + type: "Point" + } + }, + { + type: "Feature", + properties: { + id: 1, + title: "Point 1", + iconUrl: './assets/icons/icon-72x72.png' + }, + geometry: { + coordinates: [ + 28.079737800003755, + -26.165098479883348 + ], + type: "Point" + } + }, + { + type: "Feature", + properties: { + id: 1, + title: "Point 1", + iconUrl: './assets/icons/icon-72x72.png' + }, + geometry: { + coordinates: [ + 106.82649176443738, + -6.124589176175903 + ], + type: "Point" + } +} + ] + }, + visible: false, + popup: true + }), ]; layers.map(l => this.twoDlayerSvc.addLayer(l, 'Overlays')); diff --git a/projects/demo-maps/src/assets/icons/icon-72x72.png b/projects/demo-maps/src/assets/icons/icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..88eaa84c36f31d213f4e5c9dbd00aa7e7883758e GIT binary patch literal 5258 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 -
\ No newline at end of file +
+
+ +
+
+
+
+
diff --git a/projects/map-cesium/src/lib/map-cesium.component.scss b/projects/map-cesium/src/lib/map-cesium.component.scss index acbbe57e6..eaa5f6f52 100644 --- a/projects/map-cesium/src/lib/map-cesium.component.scss +++ b/projects/map-cesium/src/lib/map-cesium.component.scss @@ -12,6 +12,7 @@ width: 100%; height: 100%; position: relative; + overflow: hidden; } .cesium-viewer-bottom .cesium-credit-logoContainer { @@ -70,4 +71,59 @@ fill: var(--ukis-popup-bg-color); stroke: #0072a3; stroke-width: 1.1px; -} \ No newline at end of file +} + +.cesium-popup { + position: absolute; + background-color: var(--ukis-popup-bg-color); + -webkit-filter: var(--ukis-drop-shadow); + filter: var(--ukis-drop-shadow); + padding: 15px; + border-radius: 2px; + top: 0px; + left: 0px; + margin: 0.5rem; + min-width: 280px; + display:none; + z-index: 1000000; + + .cesium-popup-closer { + text-decoration: none; + position: absolute; + top: 0px; + right: 8px; + cursor: pointer; + } + + .cesium-popup-closer:after { + content: "✖"; + } + + &:after, + &:before { + top: 100%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-top-color: var(--ukis-popup-bg-color); + border-width: 10px; + left: 48px; + margin-left: -10px; + } + + &:before { + border-width: 11px; + left: 48px; + margin-left: -11px; + } + + &.hidden { + visibility: hidden; + } +} diff --git a/projects/map-cesium/src/lib/map-cesium.component.ts b/projects/map-cesium/src/lib/map-cesium.component.ts index 8d43000c1..ac278960b 100644 --- a/projects/map-cesium/src/lib/map-cesium.component.ts +++ b/projects/map-cesium/src/lib/map-cesium.component.ts @@ -2,11 +2,11 @@ import { Component, OnInit, ViewEncapsulation, Input, OnDestroy, AfterViewInit, import { IMapStateOptions, MapState, MapStateService } from '@dlr-eoc/services-map-state'; import { Subscription, Subject } from 'rxjs'; -import { filter, skip } from 'rxjs/operators'; +import { skip } from 'rxjs/operators'; import { MapCesiumService } from './map-cesium.service'; import { LayersService, Layer, TFiltertypes, TFiltertypesUncap } from '@dlr-eoc/services-layers'; import { Viewer } from '@cesium/widgets'; -import { GeoJsonDataSource } from '@cesium/engine'; +import { ScreenSpaceEventHandler, ScreenSpaceEventType, GeoJsonDataSource } from '@cesium/engine'; export interface ICesiumControls { @@ -22,11 +22,14 @@ export interface ICesiumControls { fullscreenButton?: boolean; scene3DOnly?: boolean; infoBox?: boolean; + selectionIndicator?: boolean; + enablePopups?: boolean; //Also you can define an Cesium ion Access Token, https://cesium.com/learn/ion/cesium-ion-access-tokens/ ionAccessToken?: string; //In the same way you can provide a personal key for Google Maps, https://cesium.com/learn/cesiumjs-learn/cesiumjs-photorealistic-3d-tiles/ GoogleMapsApiKey?: string; - selectionIndicator?: boolean; + //default globe color as hex string + globeColor?: string; } declare type Tgroupfiltertype = TFiltertypesUncap | TFiltertypes; @@ -64,6 +67,7 @@ export class MapCesiumComponent implements OnInit, AfterViewInit, OnDestroy { console.error(`provide a MapStateService as Input to ukis-map-cesium`); } this.mapSvc.removeAll2DLayers(); + //Set start time, if available if (this.startTime) { this.mapSvc.initTime(this.startTime); @@ -181,15 +185,13 @@ export class MapCesiumComponent implements OnInit, AfterViewInit, OnDestroy { } private subscribeToMapEvents() { - // https://github.com/CesiumGS/cesium/blob/99d6fffe20d9cf19f2d70de97777dc00a435bc5e/packages/engine/Source/Scene/Camera.js#L223-L224 - // The amount the camera has to change before the event is raised is 0.5 - // this.viewer.camera.percentageChanged = 0.1; this.viewer.camera.changed.addEventListener((evt) => { const ms = this.calcMapStateFromCamera('map'); this.mapStateSvc.setMapState(ms); }); - //Changing entitiy parameters for the display in he infoBox window + if(this.controls.infoBox){ + //Changing entitiy parameters for the display in he infoBox window this.viewer.selectedEntityChanged.addEventListener(() => { const entity = this.viewer.selectedEntity; //change infoBox title @@ -212,6 +214,41 @@ export class MapCesiumComponent implements OnInit, AfterViewInit, OnDestroy { } } }); + } + + //Show the popup on click + if(this.controls.enablePopups){ + const cesiumEventHandler = new ScreenSpaceEventHandler(this.viewer.scene.canvas); + cesiumEventHandler.setInputAction((e:any) => { + //get camera ray at picked position and get layer features at picked location + const ray = this.viewer.camera.getPickRay(e.position)!; + const entity = this.viewer.scene.imageryLayers.pickImageryLayerFeatures(ray, this.viewer.scene); + if(entity){ + const popupContent = document.getElementById("map_cesium_popup_content")!; + const popupDiv = popupContent.parentElement; + const entity_x = e.position.x; + const entity_y = e.position.y + + //hide popup while waiting for the content to load + popupDiv.style.display = 'none'; + + entity?.then(e =>{ + //write description text to popup + popupContent.innerHTML = e[0].description!; + popupDiv.style.left = (entity_x-58) + 'px'; + popupDiv.style.top = (entity_y-78) + 'px'; + popupDiv.style.display = 'block'; + } + ); + } + }, ScreenSpaceEventType.LEFT_CLICK); + + //Hide the popup + cesiumEventHandler.setInputAction((e:any) => { + const popup = document.getElementById("cesium_popup_div")!; + popup.style.display = 'none'; + }, ScreenSpaceEventType.RIGHT_DOWN); + } } @@ -243,9 +280,6 @@ export class MapCesiumComponent implements OnInit, AfterViewInit, OnDestroy { private update2DBaseLayers(layers: Layer[]) { this.mapSvc.update2DLayerVisibility(layers, 'baselayers'); - //In current application the folllowing map control functions are not enabled for baselayers - //this.mapSvc.updateLayerOpacity(layers, 'baselayers'); - //this.mapSvc.updateLayerZIndex(layers, 'baselayers'); } private addUpdateTerrainLayers(layers: Layer[]) { @@ -319,4 +353,9 @@ export class MapCesiumComponent implements OnInit, AfterViewInit, OnDestroy { this.mapSvc.update3DLayerOpacity(layers, filtertype); } + closeCesiumPopup(){ + const popup = document.getElementById("cesium_popup_div")!; + popup.style.display = 'none'; + } + } diff --git a/projects/map-cesium/src/lib/map-cesium.service.spec.ts b/projects/map-cesium/src/lib/map-cesium.service.spec.ts index f67ab7bb4..17efbac83 100644 --- a/projects/map-cesium/src/lib/map-cesium.service.spec.ts +++ b/projects/map-cesium/src/lib/map-cesium.service.spec.ts @@ -163,8 +163,7 @@ describe('MapCesiumService Core Functions', () => { service = TestBed.inject(MapCesiumService); const controls: ICesiumControls = { - infoBox: true, - selectionIndicator: true + enablePopups: true } service.setControls(controls); }); @@ -195,8 +194,7 @@ describe('MapCesiumService State', () => { service = TestBed.inject(MapCesiumService); const controls: ICesiumControls = { - infoBox: true, - selectionIndicator: true + enablePopups: true } service.setControls(controls); }); @@ -267,8 +265,7 @@ describe('MapCesiumService Layer Functions', () => { service = TestBed.inject(MapCesiumService); const controls: ICesiumControls = { - infoBox: true, - selectionIndicator: true + enablePopups: true } service.setControls(controls); }); @@ -354,8 +351,7 @@ describe('MapCesiumService ukisLayers', () => { service = TestBed.inject(MapCesiumService); const controls: ICesiumControls = { - infoBox: true, - selectionIndicator: true + enablePopups: true } service.setControls(controls); createTestLayer(); @@ -477,8 +473,7 @@ describe('MapCesiumService DataSources', () => { service = TestBed.inject(MapCesiumService); const controls: ICesiumControls = { - infoBox: true, - selectionIndicator: true + enablePopups: true } service.setControls(controls); createTestLayer(); diff --git a/projects/map-cesium/src/lib/map-cesium.service.ts b/projects/map-cesium/src/lib/map-cesium.service.ts index 7bab0cf7c..cf4699666 100644 --- a/projects/map-cesium/src/lib/map-cesium.service.ts +++ b/projects/map-cesium/src/lib/map-cesium.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Layer, VectorLayer, CustomLayer, RasterLayer, WmtsLayer, WmsLayer, TGeoExtent, TmsLayertype, WmtsLayertype, WmsLayertype, XyzLayertype, IListMatrixSet, TFiltertypesUncap, TFiltertypes } from '@dlr-eoc/services-layers'; import { ICesiumControls } from './map-cesium.component'; -import { Cartesian3, Cesium3DTileStyle, Cesium3DTileset, CesiumTerrainProvider, Color, Credit, DataSource, EllipsoidTerrainProvider, GeoJsonDataSource, I3SDataProvider, ImageryLayer, Ion, JulianDate, KmlDataSource, Rectangle, TileMapServiceImageryProvider, TimeIntervalCollection, UrlTemplateImageryProvider, WebMapServiceImageryProvider, WebMapTileServiceImageryProvider, WebMercatorTilingScheme, Math as CesiumMath} from '@cesium/engine'; +import { Cartesian3, Cesium3DTileStyle, Cesium3DTileset, CesiumTerrainProvider, Color, Credit, DataSource, EllipsoidTerrainProvider, GeoJsonDataSource, I3SDataProvider, ImageryLayer, Ion, JulianDate, KmlDataSource, Rectangle, TileMapServiceImageryProvider, TimeIntervalCollection, UrlTemplateImageryProvider, WebMapServiceImageryProvider, WebMapTileServiceImageryProvider, WebMercatorTilingScheme, Math as CesiumMath, BillboardGraphics} from '@cesium/engine'; import { Viewer } from '@cesium/widgets'; import { IMapCenter } from '@dlr-eoc/services-map-state'; @@ -55,9 +55,10 @@ export class MapCesiumService { infoBox: false, selectionIndicator: false, baseLayer: false - }; + public defaultGlobeColor: Color = Color.WHITE; + constructor() { this.EPSG = WebMercator; } @@ -104,6 +105,9 @@ export class MapCesiumService { if (typeof newControls.selectionIndicator !== 'undefined') { this.viewerOptions.selectionIndicator = newControls.selectionIndicator; } + if (typeof newControls.globeColor !== 'undefined') { + this.defaultGlobeColor = Color.fromCssColorString(newControls.globeColor); + } } //Create Cesium Viewer @@ -117,16 +121,27 @@ export class MapCesiumService { const scene = this.viewer.scene; scene.fog.enabled = false; scene.globe.showGroundAtmosphere = false; + scene.sun.show = false; + scene.moon.show = false; + + //reduce light effect on tilesets + scene.globe.enableLighting = false; + scene.highDynamicRange = false; + + //set default color to white for transparent backgrounds + scene.globe.baseColor = this.defaultGlobeColor; //set start time this.viewer.clock.currentTime = this.cesiumCurrentTime; //change default infoBox + if(this.viewerOptions.infoBox){ this.viewer.infoBox.container.getElementsByTagName('iframe')[0].remove(); const newDiv = document.createElement("div"); newDiv.className = 'cesium-infoBox-content'; newDiv.id = 'cesiumInfoBoxContent' this.viewer.infoBox.container.children[0].append(newDiv); + } //Change primitive collection settings this.viewer.scene.primitives.destroyPrimitives = false; @@ -256,6 +271,7 @@ export class MapCesiumService { } }else{ // If view angle is 0, setViewAngle(0) (flyTo) is not necessary + console.log(typeof options.complete); if(options.complete && typeof options.complete === 'function'){ options.complete(); } @@ -609,7 +625,7 @@ export class MapCesiumService { wmtsOptions.rectangle = Rectangle.fromDegrees(l.bbox[0], l.bbox[1], l.bbox[2], l.bbox[3]); } if (l.popup) { - //Not supported by cesium as 02/2023 + //Not supported by cesium as 07/2024, https://cesium.com/learn/cesiumjs/ref-doc/WebMapTileServiceImageryProvider.html#pickFeatures } const newImageryLayer = new ImageryLayer( new WebMapTileServiceImageryProvider(wmtsOptions), @@ -684,7 +700,22 @@ export class MapCesiumService { dataSourceOptions.credit = new Credit(l.attribution); } - newGeoJsonDataSource.load(l.data, dataSourceOptions); + newGeoJsonDataSource.load(l.data, dataSourceOptions).then(function(){ + let i = 0; + const entityArray = newGeoJsonDataSource.entities.values; + //check if vector data has icon features and set the icon graphic accordingly + entityArray.forEach(entity => { + if(l.data['features'] && l.data['features'][i]['properties'] && l.data['features'][i]['properties']['iconUrl']){ + entity.billboard = new BillboardGraphics({ + image: l.data['features'][i]['properties']['iconUrl'], + width: 20, + height: 20 + }); + entity.description = l.data['features'][i]['properties']['id']; + } + i++; + }); + }); newGeoJsonDataSource.show = l.visible; newGeoJsonDataSource.name = l.name; @@ -1148,11 +1179,16 @@ export class MapCesiumService { if (new_tileset_layer.style == undefined) { new_tileset_layer.style = new Cesium3DTileStyle({ "show": "true", - "color": "color('lightgrey'," + tilesetLayer.opacity + ")" + "color": "color('white'," + tilesetLayer.opacity + ")" }); } new_tileset_layer.credit = new Credit(tilesetLayer.attribution!); + //set the luminance of the tileset. A high value reduces the day/night sun based lighting effect. Default value is 0.2 + if(tilesetLayer.custom_layer.imageBasedLighting){ + new_tileset_layer.imageBasedLighting.luminanceAtZenith = tilesetLayer.custom_layer.imageBasedLighting.luminanceAtZenith; + } + this.tilesetLayerGroup.set(tilesetLayer.id, new_tileset_layer); } catch (error) { console.log(`There was an error creating the 3D Data Provider: ${error}`); @@ -1243,10 +1279,14 @@ export class MapCesiumService { } addIonAccessToken(token: string) { - Ion.defaultAccessToken = token; + if(token){ + Ion.defaultAccessToken = token; + } } addGoogleMapsApiKey(key: string) { + if(key){ //GoogleMaps.defaultApiKey = key; + } } destroyLayerGrpoups() {