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