From 53f8f3004e68903425e81509c97e2aa1dd549645 Mon Sep 17 00:00:00 2001 From: Holger Stolzenberg Date: Mon, 11 Mar 2024 12:43:24 +0100 Subject: [PATCH] Show my own location in map --- src/app/map/geo.service.ts | 9 +++--- src/app/map/map.constants.ts | 16 +++++++---- src/app/map/map.service.ts | 54 ++++++++++++++++++++++++++++++------ 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/app/map/geo.service.ts b/src/app/map/geo.service.ts index 9714a35..a91b1c6 100644 --- a/src/app/map/geo.service.ts +++ b/src/app/map/geo.service.ts @@ -6,7 +6,8 @@ import { NotificationService } from '../notifications/notification.service'; export class GeoService { private readonly options = { enableHighAccuracy: false, timeout: 5000 }; - constructor(private readonly notificationService: NotificationService) {} + constructor(private readonly notificationService: NotificationService) { + } myCurrentLocation() { return new Observable(observer => { @@ -20,8 +21,8 @@ export class GeoService { ); }).pipe( tap(coords => { - const longitude = this.degreesMinutes(coords.longitude); const latitude = this.degreesMinutes(coords.latitude); + const longitude = this.degreesMinutes(coords.longitude); this.notificationService.showInfoLocalized( 'map.got-geo-location', @@ -47,11 +48,11 @@ export class GeoService { } formatDegreesMinutes(value: DegreeMinute) { - return value.degrees + '°' + value.minutes + '"' + value.seconds + "'"; + return value.degrees + '°' + value.minutes + '"' + value.seconds + '\''; } } class DegreeMinute { - constructor(readonly degrees: number,readonly minutes: number,readonly seconds: number) { + constructor(readonly degrees: number, readonly minutes: number, readonly seconds: number) { } } diff --git a/src/app/map/map.constants.ts b/src/app/map/map.constants.ts index 65a62a7..af949f2 100644 --- a/src/app/map/map.constants.ts +++ b/src/app/map/map.constants.ts @@ -7,8 +7,8 @@ export const DEFAULT_TRANSITION_DURATION_MS = 'auto'; export const FLY_TO_ZOOM = 7; export const MAP_CENTER = { - longitude: 15.2551, - latitude: 49 + latitude: 49, + longitude: 15.2551 }; export const INITIAL_VIEW_STATE: Record = { @@ -21,12 +21,15 @@ export const INITIAL_VIEW_STATE: Record = { bearing: 0 }; -export const BERLIN = [52.52, 13.405]; +export const BERLIN = { + latitude: 52.52, + longitude: 13.405 +}; // TODO feature: capitol names, population export const CAPITOLS_LAYER = new ScatterplotLayer({ id: 'capitols-layer', - data: [{ coordinates: BERLIN, radius: 30 }], + data: [{ latitude: BERLIN.latitude, longitude: BERLIN.longitude, radius: 30 }], pickable: false, radiusScale: 6, radiusMinPixels: 1, @@ -38,7 +41,7 @@ export const CAPITOLS_LAYER = new ScatterplotLayer({ visible: true, getRadius: () => 2000, - getPosition: d => [d.coordinates[1], d.coordinates[0], 50], // need a bit of altitude for proper rendering + getPosition: d => [d.longitude, d.latitude, 50], // need a bit of altitude for proper rendering getLineColor: () => [255, 214, 23, 255], getFillColor: () => [255, 214, 23, 50], getLineWidth: () => 3000 @@ -47,5 +50,6 @@ export const CAPITOLS_LAYER = new ScatterplotLayer({ export enum LayerIndices { MAP_LAYER = 0, EU_BORDERS_LAYER = 1, - CAPITOLS_LAYER = 2 + CAPITOLS_LAYER = 2, + MY_LOCATION_LAYER = 3 } diff --git a/src/app/map/map.service.ts b/src/app/map/map.service.ts index 77ccba7..be94ed8 100644 --- a/src/app/map/map.service.ts +++ b/src/app/map/map.service.ts @@ -12,7 +12,7 @@ import { } from './map.constants'; import { NotificationService } from '../notifications/notification.service'; import { Deck, FlyToInterpolator, Layer } from '@deck.gl/core/typed'; -import { BitmapLayer, GeoJsonLayer } from '@deck.gl/layers/typed'; +import { BitmapLayer, GeoJsonLayer, ScatterplotLayer } from '@deck.gl/layers/typed'; import { catchError, delay, firstValueFrom, forkJoin, map, Observable, of, Subject } from 'rxjs'; import { TileLayer } from '@deck.gl/geo-layers/typed'; import { environment } from '../../environments/environment'; @@ -69,19 +69,21 @@ export class MapService { } async resetMapToEuropeanCenter() { - return this.transitionMapAnimated(MAP_CENTER.longitude, MAP_CENTER.latitude, DEFAULT_ZOOM); + return this.hideMyLocation().then(() => this.transitionMapAnimated(MAP_CENTER.latitude, MAP_CENTER.longitude, DEFAULT_ZOOM)); } async moveMapToMyLocation() { + this.loadingIndicator$?.next(true); + if (this.myLocation) { - return this.transitionMapAnimated(this.myLocation.longitude, this.myLocation.latitude, FLY_TO_ZOOM); + await this.addMyLocation(this.myLocation.latitude, this.myLocation.longitude); + return this.transitionMapAnimated(this.myLocation.latitude, this.myLocation.longitude, 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); + this.addMyLocation(this.myLocation.latitude, this.myLocation.longitude); + this.transitionMapAnimated(coordinates.latitude, coordinates.longitude, FLY_TO_ZOOM); }); } @@ -150,7 +152,7 @@ export class MapService { }); } - private async transitionMapAnimated(longitude: number, latitude: number, zoom: number) { + private async transitionMapAnimated(latitude: number, longitude: number, zoom: number) { return new Promise(() => { this.loadingIndicator$?.next(true); @@ -223,7 +225,43 @@ export class MapService { const clonedLayers = this.layers.slice(); clonedLayers[index] = this.layers[index].clone({ visible: value }); - this.theMap!.setProps({ layers: clonedLayers }); this.layers = clonedLayers; + this.theMap!.setProps({ layers: clonedLayers }); + } + + private async addMyLocation(latitude: number, longitude: number) { + if (this.layers.length == 4) { + return this.changeLayerVisibility(LayerIndices.MY_LOCATION_LAYER, true); + } + console.log('---', latitude, longitude); + const updated = this.layers.slice(); + updated.push(new ScatterplotLayer({ + id: 'my-location-layer', + data: [{ latitude: latitude, longitude: longitude, radius: 30 }], + pickable: false, + radiusScale: 6, + radiusMinPixels: 1, + radiusMaxPixels: 1000, + lineWidthMinPixels: 1, + stroked: true, + filled: true, + colorFormat: 'RGBA', + visible: true, + + getRadius: () => 2000, + getPosition: d => [d.longitude, d.latitude, 50], // need a bit of altitude for proper rendering + getLineColor: () => [38, 38, 185, 255], + getFillColor: () => [38, 38, 185, 50], + getLineWidth: () => 3000 + })); + + this.layers = updated; + this.theMap!.setProps({ layers: updated }); + } + + private async hideMyLocation() { + if (this.layers.length == 4) { + return this.changeLayerVisibility(LayerIndices.MY_LOCATION_LAYER, false); + } } }