Implementing a Marker component.
This commit is contained in:
parent
925174db79
commit
1ed4875e5e
20
src/App.tsx
20
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 = (
|
||||
<Marker
|
||||
coordinates={{ lat: -37.8403508, lon: 77.5539501 }}
|
||||
icon={
|
||||
<circle
|
||||
cx={0}
|
||||
cy={0}
|
||||
r={6 / 256}
|
||||
fill='blue'
|
||||
opacity='90%'
|
||||
stroke='white'
|
||||
strokeWidth={3 / 256}
|
||||
strokeOpacity='100%'
|
||||
></circle>
|
||||
}
|
||||
key='current'
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<IonApp>
|
||||
<IonContent fullscreen={true}>
|
||||
|
@ -70,6 +89,7 @@ const App: React.FC = () => {
|
|||
scope={scope}
|
||||
setScope={debounce(setScope, 1000)}
|
||||
numberOfTiledLayers={5}
|
||||
markers={[marker]}
|
||||
/>
|
||||
</IonApp>
|
||||
</IonContent>
|
||||
|
|
|
@ -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<any, string | JSXElementConstructor<any>>[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,6 +92,7 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
|||
<svg width='100%' height='100%' data-testid='layer-stack'>
|
||||
<g
|
||||
transform={`translate(${props.coordinateSystem.shift.x}, ${props.coordinateSystem.shift.y}) scale(${props.coordinateSystem.zoom})`}
|
||||
key='tiles'
|
||||
>
|
||||
{
|
||||
// Tiled layers with less detail
|
||||
|
@ -98,6 +109,23 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
|||
getTiledLayer(activeTiledLayer)
|
||||
}
|
||||
</g>
|
||||
{props.markers !== undefined ? (
|
||||
<g
|
||||
key='markers'
|
||||
transform={`translate(${props.coordinateSystem.shift.x}, ${props.coordinateSystem.shift.y}) scale(${props.coordinateSystem.zoom})`}
|
||||
>
|
||||
<g
|
||||
transform={`scale(256) translate(-${props.keyObject.x}, -${props.keyObject.y})`}
|
||||
>
|
||||
{props.markers.map((marker) =>
|
||||
cloneElement(marker, {
|
||||
keyObject: props.keyObject,
|
||||
zoom: props.coordinateSystem.zoom,
|
||||
})
|
||||
)}
|
||||
</g>
|
||||
</g>
|
||||
) : null}
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<any, string | JSXElementConstructor<any>>[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,7 +135,11 @@ export const LiveMap: react.FC<LiveMapProperties> = (
|
|||
return (
|
||||
<div style={{ width: '100%', height: '100%' }} ref={observe}>
|
||||
<Handlers transformMap={transform} />
|
||||
<Map scope={scope} numberOfTiledLayers={props.numberOfTiledLayers} />
|
||||
<Map
|
||||
scope={scope}
|
||||
numberOfTiledLayers={props.numberOfTiledLayers}
|
||||
markers={props.markers}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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<any, string | JSXElementConstructor<any>>[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +62,7 @@ export const Map: react.FC<MapProperties> = (props: MapProperties) => {
|
|||
},
|
||||
zoom: relativeScale,
|
||||
}}
|
||||
markers={props.markers}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -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<MarkerProperties> = (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 (
|
||||
<g transform={`translate(${x}, ${y}) scale(${1 / props.zoom})`}>
|
||||
{props.icon}
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
export default Marker;
|
|
@ -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<TiledLayerProperties> = (
|
|||
};
|
||||
}
|
||||
return (
|
||||
<g
|
||||
transform={`scale(${props.zoom}) translate(${props.shift.x}, ${props.shift.y})`}
|
||||
ref={g}
|
||||
>
|
||||
<TileSet
|
||||
keyObject={{
|
||||
provider: props.keyObject.provider,
|
||||
zoomLevel: props.keyObject.zoomLevel,
|
||||
x: 0,
|
||||
y: 0,
|
||||
}}
|
||||
viewPort={viewPort}
|
||||
/>
|
||||
</g>
|
||||
<>
|
||||
<g
|
||||
transform={`scale(${props.zoom}) translate(${props.shift.x}, ${props.shift.y})`}
|
||||
ref={g}
|
||||
>
|
||||
<TileSet
|
||||
keyObject={{
|
||||
provider: props.keyObject.provider,
|
||||
zoomLevel: props.keyObject.zoomLevel,
|
||||
x: 0,
|
||||
y: 0,
|
||||
}}
|
||||
viewPort={viewPort}
|
||||
/>
|
||||
</g>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue