2022-10-17 15:15:24 +00:00
|
|
|
import react, { useRef } from 'react';
|
|
|
|
import { range } from 'lodash';
|
2022-10-17 10:04:25 +00:00
|
|
|
|
2022-10-17 11:47:35 +00:00
|
|
|
import { Rectangle, TileKeyObject } from './types';
|
2022-10-17 15:15:24 +00:00
|
|
|
import tileUri from './uris';
|
2022-10-17 10:04:25 +00:00
|
|
|
|
|
|
|
export interface TiledLayerProperties {
|
|
|
|
/** The key of the first (ie top/left) tile */
|
2022-10-17 11:47:35 +00:00
|
|
|
keyObject: TileKeyObject;
|
|
|
|
/** The current viewport expressed in tiles coordinates */
|
|
|
|
viewPort: Rectangle;
|
2022-10-17 10:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-10-17 11:47:35 +00:00
|
|
|
* A lazily loaded square layer of tiles.
|
|
|
|
*
|
|
|
|
* This component is rather dumb and is mainly a sparse array of tiles.
|
|
|
|
* New tiles are added to the array when the viewport is updated and they stay in the array until
|
|
|
|
* the component is destroyed or its number of tiles is updated.
|
2022-10-17 10:04:25 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
export const TiledLayer: react.FC<TiledLayerProperties> = (
|
|
|
|
props: TiledLayerProperties
|
|
|
|
) => {
|
2022-10-17 15:15:24 +00:00
|
|
|
console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
|
|
|
const tiles = useRef<any>({});
|
|
|
|
|
|
|
|
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).map(
|
|
|
|
(row) => {
|
|
|
|
range(props.viewPort.topLeft.x, props.viewPort.bottomRight.x + 1).map(
|
|
|
|
(col) => {
|
|
|
|
const key = tileUri({
|
|
|
|
provider: props.keyObject.provider,
|
|
|
|
zoomLevel: props.keyObject.zoomLevel,
|
|
|
|
x: props.keyObject.x + row,
|
|
|
|
y: props.keyObject.x + col,
|
|
|
|
});
|
|
|
|
if (!Object.hasOwn(tiles.current, key)) {
|
|
|
|
tiles.current[key] = <g key={key} id={key} />;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
return <>{Object.values(tiles.current)}</>;
|
2022-10-17 10:04:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export default TiledLayer;
|