2022-10-15 10:04:18 +00:00
|
|
|
import react from 'react';
|
|
|
|
import TiledLayer from './TiledLayer';
|
|
|
|
|
|
|
|
interface Point {
|
|
|
|
x: number;
|
|
|
|
y: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface TiledLayerConductorProperties {
|
|
|
|
height: number;
|
|
|
|
width: number;
|
|
|
|
shift: Point;
|
|
|
|
zoom: number;
|
|
|
|
tileSize: number;
|
2022-10-15 12:17:24 +00:00
|
|
|
numberOfZoomLevels?: number;
|
2022-10-15 15:43:49 +00:00
|
|
|
baseZoomLevel: number;
|
|
|
|
setBaseZoomLevel: (baseZoomLevel: number) => void;
|
2022-10-15 10:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const TiledLayerConductor: react.FC<TiledLayerConductorProperties> = (
|
|
|
|
props: TiledLayerConductorProperties
|
|
|
|
) => {
|
2022-10-15 12:17:24 +00:00
|
|
|
const numberOfZoomLevels =
|
|
|
|
props.numberOfZoomLevels === undefined
|
|
|
|
? 1
|
|
|
|
: props.numberOfZoomLevels % 2 === 0
|
|
|
|
? props.numberOfZoomLevels + 1
|
|
|
|
: props.numberOfZoomLevels;
|
|
|
|
|
|
|
|
const layers = [];
|
2022-10-15 18:47:31 +00:00
|
|
|
|
|
|
|
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(
|
2022-10-15 18:47:31 +00:00
|
|
|
Math.max(Math.round(Math.log2(props.zoom)) + safetyZoomLevels, 0),
|
2022-10-15 15:30:41 +00:00
|
|
|
numberOfZoomLevels - 1
|
|
|
|
);
|
2022-10-15 12:17:24 +00:00
|
|
|
|
2022-10-15 18:15:09 +00:00
|
|
|
const getTiledLayer = (zoomLevel: number, isActive: boolean) => {
|
2022-10-15 18:47:31 +00:00
|
|
|
const zoom = 2 ** (zoomLevel - safetyZoomLevels);
|
2022-10-15 15:30:41 +00:00
|
|
|
return (
|
2022-10-15 10:04:18 +00:00
|
|
|
<TiledLayer
|
2022-10-15 18:15:09 +00:00
|
|
|
key={`layer${zoomLevel + props.baseZoomLevel}`}
|
2022-10-15 18:47:31 +00:00
|
|
|
height={props.height * zoom}
|
|
|
|
width={props.width * zoom}
|
2022-10-15 18:15:09 +00:00
|
|
|
shift={{
|
2022-10-15 18:47:31 +00:00
|
|
|
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}
|
2022-10-15 18:47:31 +00:00
|
|
|
layerZoom={1 / zoom}
|
2022-10-15 10:04:18 +00:00
|
|
|
tileSize={256}
|
2022-10-15 18:47:31 +00:00
|
|
|
nbTiles={nbTiles * zoom}
|
2022-10-15 15:30:41 +00:00
|
|
|
active={isActive}
|
2022-10-15 10:04:18 +00:00
|
|
|
/>
|
2022-10-15 12:17:24 +00:00
|
|
|
);
|
2022-10-15 15:30:41 +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++) {
|
2022-10-15 15:30:41 +00:00
|
|
|
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--) {
|
2022-10-15 15:30:41 +00:00
|
|
|
layers.push(getTiledLayer(i, false));
|
2022-10-15 12:17:24 +00:00
|
|
|
}
|
2022-10-15 15:30:41 +00:00
|
|
|
// And then, of course, the active one
|
2022-10-15 18:27:36 +00:00
|
|
|
layers.push(getTiledLayer(activeZoomLevel, true));
|
2022-10-15 12:17:24 +00:00
|
|
|
|
|
|
|
return <>{layers}</>;
|
2022-10-15 10:04:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export default TiledLayerConductor;
|