From 1ed4875e5ec398af7ecfd9996501062872ca532f Mon Sep 17 00:00:00 2001 From: evlist Date: Wed, 2 Nov 2022 21:27:29 +0100 Subject: [PATCH] Implementing a Marker component. --- src/App.tsx | 20 +++++++++++++++++++ src/components/map/LayerStack.tsx | 30 ++++++++++++++++++++++++++++- src/components/map/LiveMap.tsx | 11 +++++++++-- src/components/map/Map.tsx | 7 ++++++- src/components/map/Marker.tsx | 26 +++++++++++++++++++++++++ src/components/map/TiledLayer.tsx | 32 ++++++++++++++++--------------- 6 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 src/components/map/Marker.tsx diff --git a/src/App.tsx b/src/App.tsx index ac48aa7..5b911c0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -36,6 +36,7 @@ import GetLocation from './components/buttons/GetLocation'; import { geoPoint } from './components/map/types'; import Back from './components/buttons/Back'; import Forward from './components/buttons/Forward'; +import Marker from './components/map/Marker'; setupIonicReact(); @@ -62,6 +63,24 @@ const App: React.FC = () => { const [scope, setScope] = useAtom(scopeAtom); console.log(`App, scope: ${JSON.stringify(scope)}`); + const marker = ( + + } + key='current' + /> + ); return ( @@ -70,6 +89,7 @@ const App: React.FC = () => { scope={scope} setScope={debounce(setScope, 1000)} numberOfTiledLayers={5} + markers={[marker]} /> diff --git a/src/components/map/LayerStack.tsx b/src/components/map/LayerStack.tsx index e598dbf..1d0d610 100644 --- a/src/components/map/LayerStack.tsx +++ b/src/components/map/LayerStack.tsx @@ -1,4 +1,10 @@ -import react from 'react'; +import react, { + cloneElement, + JSXElementConstructor, + ReactComponentElement, + ReactElement, + ReactNode, +} from 'react'; import { TileKeyObject } from './types'; @@ -6,6 +12,8 @@ import { CoordinateSystem } from './LiveMap'; import { range } from 'lodash'; import tileUri from './uris'; import TiledLayer from './TiledLayer'; +import { ReactComponentOrElement } from '@ionic/react'; +import { KeyObject } from 'crypto'; export interface LayerStackProperties { /** @@ -20,6 +28,8 @@ export interface LayerStackProperties { * The coordinates system */ coordinateSystem: CoordinateSystem; + /** Markers are non scalable SVG snippets tied to geo location */ + markers?: ReactElement>[]; } /** @@ -82,6 +92,7 @@ export const LayerStack: react.FC = ( { // Tiled layers with less detail @@ -98,6 +109,23 @@ export const LayerStack: react.FC = ( getTiledLayer(activeTiledLayer) } + {props.markers !== undefined ? ( + + + {props.markers.map((marker) => + cloneElement(marker, { + keyObject: props.keyObject, + zoom: props.coordinateSystem.zoom, + }) + )} + + + ) : null} ); }; diff --git a/src/components/map/LiveMap.tsx b/src/components/map/LiveMap.tsx index 9bd9876..4b6b96d 100644 --- a/src/components/map/LiveMap.tsx +++ b/src/components/map/LiveMap.tsx @@ -1,9 +1,10 @@ -import react, { useEffect, useState } from 'react'; +import react, { JSXElementConstructor, ReactComponentElement, ReactElement, ReactNode, useEffect, useState } from 'react'; import useDimensions from 'react-cool-dimensions'; import { MapScope, Point } from './types'; import Map from './Map'; import Handlers from './Handlers'; +import Marker from './Marker'; import { tileProviders } from './tile-providers'; import { lon2tile, lat2tile, tile2lat, tile2long } from '../../lib/geo'; @@ -39,6 +40,8 @@ export interface LiveMapProperties { numberOfTiledLayers?: number; /** If provided, a function to call when the scope is updated. */ setScope?: (scope: MapScope) => void; + /** Markers are non scalable SVG snippets tied to geo location */ + markers?: ReactElement>[]; } /** @@ -132,7 +135,11 @@ export const LiveMap: react.FC = ( return (
- +
); }; diff --git a/src/components/map/Map.tsx b/src/components/map/Map.tsx index 0e20ae9..a759cb0 100644 --- a/src/components/map/Map.tsx +++ b/src/components/map/Map.tsx @@ -1,7 +1,9 @@ -import react from 'react'; +import react, { JSXElementConstructor, ReactElement, ReactNode } from 'react'; import useDimensions from 'react-cool-dimensions'; import { Point, MapScope } from './types'; +import Marker from './Marker'; + import LayerStack from './LayerStack'; import { tileProviders } from './tile-providers'; import { lon2tile, lat2tile } from '../../lib/geo'; @@ -9,6 +11,8 @@ import { lon2tile, lat2tile } from '../../lib/geo'; export interface MapProperties { scope: MapScope; numberOfTiledLayers?: number; + /** Markers are non scalable SVG snippets tied to geo location */ + markers?: ReactElement>[]; } /** @@ -58,6 +62,7 @@ export const Map: react.FC = (props: MapProperties) => { }, zoom: relativeScale, }} + markers={props.markers} /> ); diff --git a/src/components/map/Marker.tsx b/src/components/map/Marker.tsx new file mode 100644 index 0000000..20ffa6b --- /dev/null +++ b/src/components/map/Marker.tsx @@ -0,0 +1,26 @@ +import { KeyObject } from 'crypto'; +import react, { ReactNode } from 'react'; +import { lat2tile, lon2tile } from '../../lib/geo'; +import { CoordinateSystem } from './LiveMap'; +import { geoPoint, TileKeyObject } from './types'; + +export interface MarkerProperties { + coordinates: geoPoint; + icon: ReactNode; + keyObject?: TileKeyObject; + zoom?: number; +} + +export const Marker: react.FC = (props: MarkerProperties) => { + if (props.keyObject === undefined || props.zoom === undefined) return null; + + const x = lon2tile(props.coordinates.lon, props.keyObject.zoomLevel); + const y = lat2tile(props.coordinates.lat, props.keyObject.zoomLevel); + return ( + + {props.icon} + + ); +}; + +export default Marker; diff --git a/src/components/map/TiledLayer.tsx b/src/components/map/TiledLayer.tsx index 2b58266..dadb2b4 100644 --- a/src/components/map/TiledLayer.tsx +++ b/src/components/map/TiledLayer.tsx @@ -1,4 +1,4 @@ -import react, { useRef } from 'react'; +import react, { ReactNode, useRef } from 'react'; import TileSet from './TileSet'; import { Point, TileKeyObject } from './types'; import { CoordinateSystem } from './LiveMap'; @@ -75,20 +75,22 @@ export const TiledLayer: react.FC = ( }; } return ( - - - + <> + + + + ); };