dyomedea/src/components/map/Map.tsx

91 lines
2.5 KiB
TypeScript
Raw Normal View History

2022-10-18 11:45:16 +00:00
import react, { useState } from 'react';
import Handlers from './Handlers';
2022-10-17 20:37:07 +00:00
import Tile from './Tile';
import TiledLayer from './TiledLayer';
2022-10-18 11:45:16 +00:00
import { Point, TileFactory } from './types';
2022-10-17 08:37:26 +00:00
2022-10-17 10:04:25 +00:00
export interface MapProperties {}
2022-10-17 08:37:26 +00:00
2022-10-17 10:04:25 +00:00
/**
*
* @returns A Map component
*/
export const Map: react.FC<MapProperties> = (props: MapProperties) => {
2022-10-18 11:45:16 +00:00
const [coordinateSystem, setCoordinateSystem] = useState({
zoom: 1,
shift: { x: 0, y: 0 },
});
2022-10-17 20:37:07 +00:00
const simpleTileFactory: TileFactory = (keyObject) => (
<Tile
href={`https://tile.openstreetmap.org/${keyObject.zoomLevel}/${keyObject.x}/${keyObject.y}.png`}
/>
);
2022-10-18 11:45:16 +00:00
const transformMap = (
deltaShift: Point | null,
deltaZoom: number | null,
zoomCenter: Point | null
) => {
const actualDeltaShift = deltaShift === null ? { x: 0, y: 0 } : deltaShift;
const actualDeltaZoom = deltaZoom === null ? 1 : deltaZoom;
const actualZoomCenter = zoomCenter === null ? { x: 0, y: 0 } : zoomCenter;
var newCoordinateSystem = {
shift: {
x:
coordinateSystem.shift.x +
actualDeltaShift.x +
(coordinateSystem.shift.x - actualZoomCenter.x) *
(actualDeltaZoom - 1),
y:
coordinateSystem.shift.y +
actualDeltaShift.y +
(coordinateSystem.shift.y - actualZoomCenter.y) *
(actualDeltaZoom - 1),
},
zoom: coordinateSystem.zoom * actualDeltaZoom,
};
setCoordinateSystem(newCoordinateSystem);
};
2022-10-18 11:57:46 +00:00
const viewPort = {
topLeft: {
x: Math.floor(-coordinateSystem.shift.x / coordinateSystem.zoom / 256),
y: Math.floor(-coordinateSystem.shift.y / coordinateSystem.zoom / 256),
},
bottomRight: {
x: Math.ceil(
(-coordinateSystem.shift.x + window.innerWidth) /
coordinateSystem.zoom /
256
),
y: Math.ceil(
(-coordinateSystem.shift.y + window.innerHeight) /
coordinateSystem.zoom /
256
),
},
};
2022-10-17 20:37:07 +00:00
return (
2022-10-18 11:45:16 +00:00
<>
<Handlers transformMap={transformMap} />
<svg width={window.innerWidth} height={window.innerHeight}>
<g
transform={`translate(${coordinateSystem.shift.x}, ${coordinateSystem.shift.y}) scale(${coordinateSystem.zoom})`}
>
<g transform='scale(256)'>
<TiledLayer
keyObject={{ provider: 'osm', zoomLevel: 16, x: 33485, y: 23936 }}
2022-10-18 11:57:46 +00:00
viewPort={viewPort}
2022-10-18 11:45:16 +00:00
tileFactory={simpleTileFactory}
/>
</g>
</g>
</svg>
</>
2022-10-17 20:37:07 +00:00
);
2022-10-17 08:37:26 +00:00
};
export default Map;