Adding the Tile component.
This commit is contained in:
parent
f6a0eb8963
commit
42e2d7c2c7
|
@ -0,0 +1,45 @@
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import Tile from './Tile';
|
||||||
|
|
||||||
|
describe('The Tile component ', () => {
|
||||||
|
test('Is initially empty', () => {
|
||||||
|
const { baseElement } = render(
|
||||||
|
<svg>
|
||||||
|
<Tile href='http://fakeurl' size={256} delay={10000} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
screen.debug();
|
||||||
|
expect(baseElement).toMatchInlineSnapshot(`
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<svg>
|
||||||
|
<g />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
test('Gets its image immediately with a fake URL', () => {
|
||||||
|
const { baseElement } = render(
|
||||||
|
<svg>
|
||||||
|
<Tile href='http://fakeurl' size={256} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
screen.debug();
|
||||||
|
expect(baseElement).toMatchInlineSnapshot(`
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<svg>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="256"
|
||||||
|
href="http://fakeurl"
|
||||||
|
width="256"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,53 @@
|
||||||
|
import react, { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
export interface TileProperties {
|
||||||
|
// The image's source URL
|
||||||
|
href: string;
|
||||||
|
// Its size
|
||||||
|
size: number;
|
||||||
|
// A delay to add (for test/debug purposes)
|
||||||
|
delay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param props
|
||||||
|
* @returns A tile
|
||||||
|
*/
|
||||||
|
export const Tile: react.FC<TileProperties> = (props: TileProperties) => {
|
||||||
|
const g = useRef<SVGGElement>(null);
|
||||||
|
|
||||||
|
const timeout = (ms: number) => {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadImage = async () => {
|
||||||
|
console.log(`Pre loading: ${props.href}`);
|
||||||
|
const image = new Image(props.size, props.size);
|
||||||
|
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;
|
||||||
|
svgImage.setAttribute('width', props.size.toString());
|
||||||
|
svgImage.setAttribute('height', props.size.toString());
|
||||||
|
// @ts-ignore
|
||||||
|
svgImage.setAttribute('href', props.href);
|
||||||
|
g.current?.replaceChildren(svgImage);
|
||||||
|
};
|
||||||
|
loadImage();
|
||||||
|
}, [props.href, props.size]);
|
||||||
|
|
||||||
|
return <g ref={g} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tile;
|
Loading…
Reference in New Issue