sandbox/svgmap/src/components/map/TiledLayersStack.tsx

94 lines
2.4 KiB
TypeScript
Raw Normal View History

2022-10-16 13:58:04 +00:00
import react, { useState } from 'react';
2022-10-15 10:04:18 +00:00
import TiledLayer from './TiledLayer';
2022-10-16 13:58:04 +00:00
import { tileKeyToString } from './Map';
2022-10-15 10:04:18 +00:00
interface Point {
x: number;
y: number;
}
2022-10-16 09:53:05 +00:00
interface TiledLayersStackProperties {
2022-10-15 10:04:18 +00:00
height: number;
width: number;
shift: Point;
zoom: number;
tileSize: number;
numberOfZoomLevels?: number;
2022-10-15 10:04:18 +00:00
}
2022-10-16 09:53:05 +00:00
const TiledLayersStack: react.FC<TiledLayersStackProperties> = (
props: TiledLayersStackProperties
2022-10-15 10:04:18 +00:00
) => {
2022-10-16 12:52:26 +00:00
console.log(`Rendering TiledLayersStack`);
2022-10-16 13:58:04 +00:00
const [tiledLayerKey, setTiledLayerKey] = useState({
provider: 'osm',
zoomLevel: 16,
x: 33488,
y: 23939,
});
2022-10-16 12:52:26 +00:00
const numberOfZoomLevels =
props.numberOfZoomLevels === undefined
? 1
: props.numberOfZoomLevels % 2 === 0
? props.numberOfZoomLevels + 1
: props.numberOfZoomLevels;
const layers = [];
const safetyZoomLevels = Math.floor(numberOfZoomLevels / 2);
const nbTiles =
Math.ceil(
(Math.max(props.width, props.height) * 2 ** safetyZoomLevels) / 256
) + 2;
2022-10-15 18:27:36 +00:00
const activeZoomLevel = Math.min(
Math.max(Math.round(Math.log2(props.zoom)) + safetyZoomLevels, 0),
numberOfZoomLevels - 1
);
2022-10-15 18:15:09 +00:00
const getTiledLayer = (zoomLevel: number, isActive: boolean) => {
const zoom = 2 ** (zoomLevel - safetyZoomLevels);
2022-10-16 12:52:26 +00:00
const currentTiledLayerKey = {
provider: tiledLayerKey.provider,
2022-10-16 13:54:53 +00:00
zoomLevel: zoomLevel - safetyZoomLevels + tiledLayerKey.zoomLevel,
x: Math.floor(tiledLayerKey.x * zoom),
y: Math.floor(tiledLayerKey.y * zoom),
2022-10-16 12:52:26 +00:00
};
return (
2022-10-15 10:04:18 +00:00
<TiledLayer
2022-10-16 12:59:09 +00:00
key={tileKeyToString(currentTiledLayerKey)}
2022-10-16 12:52:26 +00:00
tiledLayerKey={currentTiledLayerKey}
height={props.height * zoom}
width={props.width * zoom}
2022-10-15 18:15:09 +00:00
shift={{
x: props.shift.x * zoom,
y: props.shift.y * zoom,
2022-10-15 18:15:09 +00:00
}}
2022-10-15 10:04:18 +00:00
zoom={props.zoom}
layerZoom={1 / zoom}
2022-10-15 10:04:18 +00:00
tileSize={256}
nbTiles={nbTiles * zoom}
active={isActive}
2022-10-15 10:04:18 +00:00
/>
);
};
// First (ie last) dispay layers with less details (ascending order)
2022-10-15 18:27:36 +00:00
for (let i = 0; i < activeZoomLevel; i++) {
layers.push(getTiledLayer(i, false));
}
// then dispay layers with more details (descending order)
2022-10-15 18:27:36 +00:00
for (let i = numberOfZoomLevels - 1; i > activeZoomLevel; i--) {
layers.push(getTiledLayer(i, false));
}
// And then, of course, the active one
2022-10-15 18:27:36 +00:00
layers.push(getTiledLayer(activeZoomLevel, true));
return <>{layers}</>;
2022-10-15 10:04:18 +00:00
};
2022-10-16 09:53:05 +00:00
export default TiledLayersStack;