Implementing a Marker component.
This commit is contained in:
1 parent
925174db79
commit
1ed4875e5e
6 files changed
+107
-19
No files matched your search
@@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user