73 lines
1.8 KiB
TypeScript
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;
|