2022-10-30 19:23:12 +00:00
|
|
|
import react, { memo } from 'react';
|
|
|
|
import { isEqual, range } from 'lodash';
|
2022-10-17 10:04:25 +00:00
|
|
|
|
2022-10-30 19:18:21 +00:00
|
|
|
import { Rectangle, TileKeyObject } from './types';
|
2022-10-17 15:15:24 +00:00
|
|
|
import tileUri from './uris';
|
2022-10-30 19:18:21 +00:00
|
|
|
import Tile from './Tile';
|
2022-10-17 10:04:25 +00:00
|
|
|
|
2022-10-20 14:58:33 +00:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2022-10-20 14:21:27 +00:00
|
|
|
export const thisIsAModule = true;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2022-10-20 14:58:33 +00:00
|
|
|
|
2022-10-20 14:21:27 +00:00
|
|
|
declare global {
|
2022-10-30 19:18:21 +00:00
|
|
|
var cacheForTileSet: any;
|
2022-10-20 14:21:27 +00:00
|
|
|
}
|
|
|
|
|
2022-10-20 14:58:33 +00:00
|
|
|
//export {};
|
2022-10-20 14:21:27 +00:00
|
|
|
|
2022-10-30 19:18:21 +00:00
|
|
|
globalThis.cacheForTileSet = new Map();
|
2022-10-20 14:21:27 +00:00
|
|
|
|
2022-10-30 19:18:21 +00:00
|
|
|
export interface TileSetProperties {
|
|
|
|
/** A partial Tile key object specifying the provider and zoom level */
|
2022-10-17 11:47:35 +00:00
|
|
|
keyObject: TileKeyObject;
|
|
|
|
/** The current viewport expressed in tiles coordinates */
|
2022-10-19 16:35:20 +00:00
|
|
|
viewPort?: Rectangle;
|
2022-10-17 10:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-10-30 19:18:21 +00:00
|
|
|
* A lazily loaded set of tiles.
|
2022-10-17 11:47:35 +00:00
|
|
|
*
|
|
|
|
* This component is rather dumb and is mainly a sparse array of tiles.
|
2022-10-17 15:48:30 +00:00
|
|
|
*
|
2022-10-17 11:47:35 +00:00
|
|
|
* New tiles are added to the array when the viewport is updated and they stay in the array until
|
2022-10-19 16:35:20 +00:00
|
|
|
* the component is destroyed.
|
2022-10-17 10:04:25 +00:00
|
|
|
*
|
2022-10-17 15:48:30 +00:00
|
|
|
* This component has no need to know the number nor the size of its tiles: tiles can be added when needed and
|
|
|
|
* its unit is the tile size (the parent component needs to transform its enclosing SVG group to adapt its units)
|
2022-10-18 14:52:24 +00:00
|
|
|
*
|
2022-10-20 14:58:33 +00:00
|
|
|
* The `globalThis.cacheForTiledLayer` global variable is used as a cache to store tiles without being subject
|
|
|
|
* to re-initialization when components are unmounted/remounted.
|
|
|
|
*
|
|
|
|
* This cache is a map of map, the first key identifying the `<TiledLayer` and the second one for `<Tile>`s.
|
|
|
|
*
|
|
|
|
* Idea stolen [on the web](https://dev.to/tiagof/react-re-mounting-vs-re-rendering-lnh)
|
|
|
|
*
|
|
|
|
* TODO: cache housekeeping
|
2022-10-29 19:16:50 +00:00
|
|
|
*
|
2022-10-17 15:48:30 +00:00
|
|
|
*
|
2022-10-17 10:04:25 +00:00
|
|
|
*/
|
2022-10-30 19:23:12 +00:00
|
|
|
export const TileSet: react.FC<TileSetProperties> = memo(
|
|
|
|
(props: TileSetProperties) => {
|
|
|
|
// console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
2022-10-20 14:21:27 +00:00
|
|
|
|
2022-10-30 19:23:12 +00:00
|
|
|
const key = tileUri({
|
|
|
|
provider: props.keyObject.provider,
|
|
|
|
zoomLevel: props.keyObject.zoomLevel,
|
|
|
|
});
|
2022-10-17 15:15:24 +00:00
|
|
|
|
2022-10-30 19:23:12 +00:00
|
|
|
const tiles: any = globalThis.cacheForTileSet.get(key) ?? new Map();
|
|
|
|
if (props.viewPort !== undefined) {
|
|
|
|
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).forEach(
|
|
|
|
(row) => {
|
|
|
|
range(
|
|
|
|
props.viewPort!.topLeft.x,
|
|
|
|
props.viewPort!.bottomRight.x + 1
|
|
|
|
).forEach((col) => {
|
|
|
|
const keyObject = {
|
|
|
|
provider: props.keyObject.provider,
|
|
|
|
zoomLevel: props.keyObject.zoomLevel,
|
|
|
|
x: props.keyObject.x + col,
|
|
|
|
y: props.keyObject.y + row,
|
|
|
|
};
|
|
|
|
const key = tileUri(keyObject);
|
|
|
|
if (!tiles.has(key)) {
|
|
|
|
tiles.set(
|
|
|
|
key,
|
|
|
|
<Tile
|
|
|
|
key={key}
|
|
|
|
keyObject={{
|
|
|
|
provider: props.keyObject.provider,
|
|
|
|
zoomLevel: props.keyObject.zoomLevel,
|
|
|
|
x: col,
|
|
|
|
y: row,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
globalThis.cacheForTileSet.set(key, tiles);
|
|
|
|
}
|
2022-10-17 15:15:24 +00:00
|
|
|
|
2022-10-30 19:23:12 +00:00
|
|
|
return <>{Array.from(tiles.values())}</>;
|
|
|
|
},
|
|
|
|
isEqual
|
|
|
|
);
|
2022-10-17 10:04:25 +00:00
|
|
|
|
2022-10-30 19:18:21 +00:00
|
|
|
export default TileSet;
|