diff --git a/app/src/gui/components/notebook/overview_map.tsx b/app/src/gui/components/notebook/overview_map.tsx index f74a9a48f..58d9bfee2 100644 --- a/app/src/gui/components/notebook/overview_map.tsx +++ b/app/src/gui/components/notebook/overview_map.tsx @@ -34,12 +34,13 @@ import Map from 'ol/Map'; import {transform} from 'ol/proj'; import {OSM} from 'ol/source'; import VectorSource from 'ol/source/Vector'; -import {Fill, Stroke, Style} from 'ol/style'; +import {Fill, RegularShape, Stroke, Style} from 'ol/style'; import CircleStyle from 'ol/style/Circle'; import {useCallback, useMemo, useRef, useState} from 'react'; import {Link} from 'react-router-dom'; import * as ROUTES from '../../../constants/routes'; import {createCenterControl} from '../map/center-control'; +import {Geolocation} from '@capacitor/geolocation'; interface OverviewMapProps { uiSpec: ProjectUIModel; @@ -139,19 +140,21 @@ export const OverviewMap = (props: OverviewMapProps) => { const mapRef = useRef(); mapRef.current = map; - const map_center = [30, -10]; + const {data: map_center, isLoading: loadingLocation} = useQuery({ + queryKey: ['current_location'], + queryFn: async (): Promise<[number, number]> => { + const position = await Geolocation.getCurrentPosition(); + return [position.coords.longitude, position.coords.latitude]; + }, + }); /** * Create the OpenLayers map element */ const createMap = useCallback(async (element: HTMLElement): Promise => { - const center = transform(map_center, 'EPSG:4326', defaultMapProjection); - const tileLayer = new TileLayer({source: new OSM()}); const view = new View({ projection: defaultMapProjection, - center: center, - zoom: 12, }); const theMap = new Map({ @@ -161,10 +164,6 @@ export const OverviewMap = (props: OverviewMapProps) => { controls: [new Zoom()], }); - theMap.addControl(createCenterControl(theMap.getView(), center)); - - theMap.getView().setCenter(center); - theMap.on('click', evt => { const feature = theMap.forEachFeatureAtPixel(evt.pixel, feature => { return feature.getProperties(); @@ -178,6 +177,49 @@ export const OverviewMap = (props: OverviewMapProps) => { return theMap; }, []); + /** + * Add a marker to the map at the current location + * + * @param map the map element + */ + const addCurrentLocationMarker = (map: Map) => { + const source = new VectorSource(); + const geoJson = new GeoJSON(); + + const stroke = new Stroke({color: 'black', width: 2}); + const layer = new VectorLayer({ + source: source, + style: new Style({ + image: new RegularShape({ + stroke: stroke, + points: 4, + radius: 10, + radius2: 0, + angle: 0, + }), + }), + }); + + // only do this if we have a real map_center + if (map_center) { + const centerFeature = { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: map_center, + }, + }; + + source.addFeature( + geoJson.readFeature(centerFeature, { + dataProjection: 'EPSG:4326', + featureProjection: map.getView().getProjection(), + }) + ); + map.addLayer(layer); + } + }; + /** * Add the features to the map and set the map view to * encompass the features. @@ -221,13 +263,27 @@ export const OverviewMap = (props: OverviewMapProps) => { map.addLayer(layer); }; + // when we have a location and a map, add the 'here' marker to the map + if (!loadingLocation && map) { + addCurrentLocationMarker(map); + if (map_center) { + const center = transform(map_center, 'EPSG:4326', defaultMapProjection); + // add the 'here' button to go to the current location + map.addControl(createCenterControl(map.getView(), center)); + } + } + + // when we have features, add them to the map + if (!loadingFeatures && map) { + addFeaturesToMap(map); + } + // callback to add the map to the DOM const refCallback = (element: HTMLElement | null) => { if (element) { if (!map) { // create map createMap(element).then((theMap: Map) => { - addFeaturesToMap(theMap); setMap(theMap); }); } else {