From 868905729354bf68828c10eb64ebba1064ccb69f Mon Sep 17 00:00:00 2001 From: Holger Stolzenberg Date: Thu, 7 Mar 2024 19:35:48 +0100 Subject: [PATCH] Internal refactoring of the map transition stuff --- src/app/map/map.component.html | 2 +- src/app/map/map.component.ts | 23 +++++++--------- src/app/map/map.constants.ts | 2 +- src/app/map/map.service.ts | 48 ++++++++++++++++++++-------------- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/app/map/map.component.html b/src/app/map/map.component.html index c2975fd..6d8b923 100644 --- a/src/app/map/map.component.html +++ b/src/app/map/map.component.html @@ -14,7 +14,7 @@
-
+
diff --git a/src/app/map/map.component.ts b/src/app/map/map.component.ts index a8a4617..6d616f3 100644 --- a/src/app/map/map.component.ts +++ b/src/app/map/map.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core'; import { MapService } from './map.service'; import { Subject, takeUntil } from 'rxjs'; import { DeckMetrics } from '@deck.gl/core/typed/lib/deck'; @@ -8,27 +8,26 @@ import { DeckMetrics } from '@deck.gl/core/typed/lib/deck'; templateUrl: './map.component.html', styleUrl: './map.component.scss' }) -export class MapComponent implements OnInit, AfterViewInit, OnDestroy { +export class MapComponent implements AfterViewInit, OnDestroy { @ViewChild('deckGlMap', { static: false }) private mapDiv?: ElementRef; - showLoader: boolean = false; showMetrics: boolean = true; loadedTileId: string = ''; + showLoader$ = new Subject(); + readonly metrics$: Subject = new Subject(); private readonly onUnsubscribe$: Subject = new Subject(); constructor(private mapService: MapService) { this.metrics$.pipe(takeUntil(this.onUnsubscribe$)); - } - - ngOnInit(): void { - this.initAllSubscriptions(); + this.mapService.loading$.pipe(takeUntil(this.onUnsubscribe$)).subscribe(tileId => this.showHideLoader(tileId)); + this.showLoader$.pipe(takeUntil(this.onUnsubscribe$)).subscribe(); } ngAfterViewInit() { - this.mapService.initDeckGlMap(this.mapDiv!, this.metrics$); + this.mapService.initDeckGlMap(this.mapDiv!, this.metrics$, this.showLoader$); } ngOnDestroy(): void { @@ -37,15 +36,13 @@ export class MapComponent implements OnInit, AfterViewInit, OnDestroy { private initAllSubscriptions() { // prettier-ignore - this.mapService.loading$ - .pipe(takeUntil(this.onUnsubscribe$)) - .subscribe(tileId => this.showHideLoader(tileId)); + } private showHideLoader(tileId: string) { this.loadedTileId = tileId; - this.showLoader = true; - setTimeout(() => (this.showLoader = false), 1000); + this.showLoader$.next(true); + setTimeout(() => this.showLoader$.next(false), 1000); } private unsubscribeAll() { diff --git a/src/app/map/map.constants.ts b/src/app/map/map.constants.ts index 44e7d53..e22ed7a 100644 --- a/src/app/map/map.constants.ts +++ b/src/app/map/map.constants.ts @@ -43,7 +43,7 @@ export const CAPITOLS_LAYER = new ScatterplotLayer({ visible: true, getRadius: () => 2000, - getPosition: d => [d.coordinates[1], d.coordinates[0], 9000], // only explicit syntax works, altitude needed for pitch map representation + getPosition: d => [d.coordinates[1], d.coordinates[0]], getLineColor: () => [255, 214, 23, 255], getFillColor: () => [255, 214, 23, 50], getLineWidth: () => 3000 diff --git a/src/app/map/map.service.ts b/src/app/map/map.service.ts index b1fbacc..bf1398d 100644 --- a/src/app/map/map.service.ts +++ b/src/app/map/map.service.ts @@ -27,10 +27,11 @@ export class MapService { private readonly euBordersLayer: Promise; private readonly layers: Promise; - private currentViewState: Record = INITIAL_VIEW_STATE; + private currentViewState = INITIAL_VIEW_STATE; private theMap?: Deck; private myLocation?: GeolocationCoordinates; + private loadingIndicator$?: Subject; constructor( private readonly http: HttpClient, @@ -57,19 +58,20 @@ export class MapService { } async resetMapToEuropeanCenter() { - this.transitionMapAnimated(MAP_CENTER.longitude, MAP_CENTER.latitude, DEFAULT_ZOOM); + return this.transitionMapAnimated(MAP_CENTER.longitude, MAP_CENTER.latitude, DEFAULT_ZOOM); } async moveMapToMyLocation() { - // TODO refactor: find a more elegant solution - if (!this.myLocation) { - firstValueFrom(this.geoService.myCurrentLocation()).then(coordinates => { - this.myLocation = coordinates; - this.transitionMapAnimated(coordinates.longitude, coordinates.latitude, FLY_TO_ZOOM); - }); - } else { - this.transitionMapAnimated(this.myLocation.longitude, this.myLocation.latitude, FLY_TO_ZOOM); + if (this.myLocation) { + return this.transitionMapAnimated(this.myLocation.longitude, this.myLocation.latitude, FLY_TO_ZOOM); } + + this.loadingIndicator$?.next(true); + + return firstValueFrom(this.geoService.myCurrentLocation()).then(coordinates => { + this.myLocation = coordinates; + this.transitionMapAnimated(coordinates.longitude, coordinates.latitude, FLY_TO_ZOOM); + }); } async doShowEuBorders(value: boolean) { @@ -82,7 +84,9 @@ export class MapService { this.changeLayerVisibility(LayerIndices.CAPITOLS_LAYER, value).then(() => this.log.trace('Show capitols', value)); } - initDeckGlMap(mapDiv: ElementRef, metricsRef: Subject) { + initDeckGlMap(mapDiv: ElementRef, metricsRef: Subject, showLoader$: Subject) { + this.loadingIndicator$ = showLoader$; + this.layers.then(layers => { this.theMap = new Deck({ parent: mapDiv.nativeElement, @@ -110,15 +114,21 @@ export class MapService { }); } - private transitionMapAnimated(longitude: number, latitude: number, zoom: number) { - this.currentViewState = Object.assign({}, this.currentViewState, { - longitude: longitude, - latitude: latitude, - zoom: zoom, - transitionInterpolator: new FlyToInterpolator(), - transitionDuration: DEFAULT_TRANSITION_DURATION_MS + private async transitionMapAnimated(longitude: number, latitude: number, zoom: number) { + return new Promise(() => { + this.loadingIndicator$?.next(true); + + this.currentViewState = Object.assign({}, this.currentViewState, { + longitude: longitude, + latitude: latitude, + zoom: zoom, + transitionInterpolator: new FlyToInterpolator(), + transitionDuration: DEFAULT_TRANSITION_DURATION_MS + }); + + this.theMap!.setProps({ viewState: this.currentViewState }); + this.loadingIndicator$?.next(true); }); - this.theMap!.setProps({ viewState: this.currentViewState }); } private async initMapLayer() {