2022-10-18 14:57:18 +00:00
|
|
|
import react, { memo, useEffect, useRef } from 'react';
|
|
|
|
import { isEqual } from 'lodash';
|
2022-10-17 19:23:57 +00:00
|
|
|
|
|
|
|
export interface TileProperties {
|
2022-10-17 19:31:21 +00:00
|
|
|
/** The image's source URL */
|
2022-10-17 19:23:57 +00:00
|
|
|
href: string;
|
2022-10-17 19:31:21 +00:00
|
|
|
/** A delay to add (for test/debug purposes) */
|
2022-10-17 19:23:57 +00:00
|
|
|
delay?: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param props
|
|
|
|
* @returns A tile
|
2022-10-17 19:31:21 +00:00
|
|
|
*
|
|
|
|
* Tile components are containers for images.
|
2022-10-18 14:57:18 +00:00
|
|
|
*
|
2022-10-17 20:37:07 +00:00
|
|
|
* They return an empty `<g/>` element immediately so that the rendering can proceed
|
|
|
|
* and append an `<image/>` element whenever the image is loaded.
|
2022-10-18 14:57:18 +00:00
|
|
|
*
|
2022-10-17 20:37:07 +00:00
|
|
|
* They are designed to be part of {@link components/map/TiledLayer!TiledLayer} components in SVG `<g/>` elements
|
2022-10-18 14:57:18 +00:00
|
|
|
* in which the unit is the tile size. In this coordinate system their size is thus always equal to 1.
|
2022-10-17 19:23:57 +00:00
|
|
|
*/
|
2022-10-18 14:57:18 +00:00
|
|
|
export const Tile: react.FC<TileProperties> = memo((props: TileProperties) => {
|
2022-10-17 19:23:57 +00:00
|
|
|
const g = useRef<SVGGElement>(null);
|
|
|
|
|
|
|
|
const timeout = (ms: number) => {
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
};
|
2022-10-18 14:57:18 +00:00
|
|
|
console.log(`Rendering tile: ${props.href}`);
|
2022-10-17 19:23:57 +00:00
|
|
|
useEffect(() => {
|
|
|
|
const loadImage = async () => {
|
|
|
|
console.log(`Pre loading: ${props.href}`);
|
2022-10-17 20:37:07 +00:00
|
|
|
const image = new Image(1, 1);
|
2022-10-17 19:23:57 +00:00
|
|
|
image.loading = 'eager';
|
|
|
|
// @ts-ignore
|
|
|
|
image.setAttribute('href', props.href);
|
|
|
|
if (!image.complete) {
|
|
|
|
await image.decode();
|
|
|
|
}
|
|
|
|
if (props.delay !== undefined) {
|
|
|
|
await timeout(props.delay);
|
|
|
|
}
|
|
|
|
const svgImage = document.createElementNS(
|
|
|
|
'http://www.w3.org/2000/svg',
|
|
|
|
'image'
|
|
|
|
) as unknown as SVGImageElement;
|
2022-10-17 20:37:07 +00:00
|
|
|
svgImage.setAttribute('width', '1');
|
|
|
|
svgImage.setAttribute('height', '1');
|
2022-10-17 19:23:57 +00:00
|
|
|
// @ts-ignore
|
|
|
|
svgImage.setAttribute('href', props.href);
|
|
|
|
g.current?.replaceChildren(svgImage);
|
|
|
|
};
|
|
|
|
loadImage();
|
2022-10-17 20:37:07 +00:00
|
|
|
}, [props.href]);
|
2022-10-17 19:23:57 +00:00
|
|
|
|
|
|
|
return <g ref={g} />;
|
2022-10-18 14:57:18 +00:00
|
|
|
}, isEqual);
|
2022-10-17 19:23:57 +00:00
|
|
|
|
|
|
|
export default Tile;
|