dyomedea/src/components/map/Marker.tsx

73 lines
1.8 KiB
TypeScript

import react, { ReactNode, useEffect } from 'react';
import { lat2tile, lon2tile } from '../../lib/geo';
import cache from '../../lib/cache';
import { geoPoint, Rectangle, TileKeyObject } from './types';
export interface MarkerProperties {
id: string;
coordinates: geoPoint;
icon: ReactNode;
keyObject?: TileKeyObject;
zoom?: number;
viewPort?: Rectangle;
className?: string;
}
export const Marker: react.FC<MarkerProperties> = (props: MarkerProperties) => {
console.log(`Rendering Marker`);
useEffect(() => {
console.log(`Marker onMount, id:${props.id}`);
return () => {
console.log(`Marker onUnmount, id:${props.id}`);
cache.delete({ cacheId: 'points', key: props.id });
};
}, []);
if (
props.keyObject === undefined ||
props.zoom === undefined ||
props.viewPort === undefined
) {
console.log(`Marker props undefined: ${JSON.stringify(props)} `);
return null;
}
const x0 = lon2tile(props.coordinates.lon, 0);
const y0 = lat2tile(props.coordinates.lat, 0);
const x = x0 * 2 ** props.keyObject.zoomLevel;
const y = y0 * 2 ** props.keyObject.zoomLevel;
if (
x < props.viewPort.topLeft.x ||
x > props.viewPort.bottomRight.x + 1 ||
y < props.viewPort.topLeft.y ||
y > props.viewPort.bottomRight.y + 1
) {
cache.delete({ cacheId: 'points', key: props.id });
console.log(
`Marker ${x}, ${y} out of viewport: ${JSON.stringify(props.viewPort)} `
);
return null;
}
cache.set({
cacheId: 'points',
key: props.id,
value: {
coordinates: props.coordinates,
point: { x: x0, y: y0 },
},
});
return (
<g
transform={`translate(${(x - props.keyObject.x) * 256}, ${
(y - props.keyObject.y) * 256
}) scale(${1 / props.zoom})`}
className={props.className}
>
{props.icon}
</g>
);
};
export default Marker;