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

113 lines
2.7 KiB
TypeScript

import react, { useEffect, useState } from 'react';
import Tile from './Tile';
import fakeTile from './FakeTile.svg';
interface Point {
x: number;
y: number;
}
interface TiledLayerProperties {
height: number;
width: number;
shift: Point;
zoom: number;
layerZoom: number;
tileSize: number;
nbTiles: number;
active: boolean;
}
const TiledLayer: react.FC<TiledLayerProperties> = (
props: TiledLayerProperties
) => {
var initialTiles: any[][] = [];
for (let row = 0; row < props.nbTiles; row++) {
let tileRow = [];
for (let col = 0; col < props.nbTiles; col++) {
tileRow.push(<g key={`${row}/${col}`} />);
}
initialTiles.push(tileRow);
}
const [tiles, setTiles] = useState(initialTiles);
useEffect(() => {
if (props.active) {
const firstVisibleTiles = {
x: Math.max(
Math.floor(-props.shift.x / props.tileSize / props.zoom),
0
),
y: Math.max(
Math.floor(-props.shift.y / props.tileSize / props.zoom),
0
),
};
const lastVisibleTiles = {
x: Math.min(
Math.ceil(
firstVisibleTiles.x + props.width / props.tileSize / props.zoom
),
props.nbTiles - 1
),
y: Math.min(
Math.ceil(
firstVisibleTiles.y + props.height / props.tileSize / props.zoom
),
props.nbTiles - 1
),
};
console.log(
`Adding new tiles if needed for ${JSON.stringify(
firstVisibleTiles
)}/${JSON.stringify(lastVisibleTiles)}.`
);
const newTiles: any[][] = [];
for (let row = 0; row < props.nbTiles; row++) {
let tileRow = [];
for (let col = 0; col < props.nbTiles; col++) {
const key = `${row}/${col}`;
if (
tiles[row][col].type === 'g' &&
row >= firstVisibleTiles.y &&
row <= lastVisibleTiles.y &&
col >= firstVisibleTiles.x &&
col <= lastVisibleTiles.x
) {
console.log(`Adding tile ${row}/${col}`);
tileRow.push(
<Tile
key={key}
href={fakeTile}
x={col * props.tileSize}
y={row * props.tileSize}
tileSize={props.tileSize}
delay={1000}
/>
);
} else {
tileRow.push(tiles[row][col]);
}
}
newTiles.push(tileRow);
}
setTiles(newTiles);
}
}, [
props.shift,
props.zoom,
props.nbTiles,
props.height,
props.width,
props.active,
props.tileSize,
]);
return <g transform={`scale(${props.layerZoom})`}>{tiles}</g>;
};
export default TiledLayer;