Using a global variable to cache <Tile>s for <TiledLayer>s.
This commit is contained in:
parent
3dee9e90d7
commit
d970b288e4
|
@ -1,9 +1,10 @@
|
||||||
import { renderHook, act, render, screen } from '@testing-library/react';
|
import { renderHook, act, render, screen } from '@testing-library/react';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import LayerStack from './LayerStack';
|
import LayerStack from './LayerStack';
|
||||||
|
import { coordinateSystemAtom, relativeCoordinateSystemAtom } from './Map';
|
||||||
|
|
||||||
describe('The LayerStack component', () => {
|
describe('The LayerStack component', () => {
|
||||||
test('generates something', () => {
|
test('generates four empty layers and a populated one', () => {
|
||||||
// const { result } = renderHook(() => useAtom(tiledLayersAtom));
|
// const { result } = renderHook(() => useAtom(tiledLayersAtom));
|
||||||
render(
|
render(
|
||||||
<LayerStack
|
<LayerStack
|
||||||
|
@ -22,18 +23,23 @@ describe('The LayerStack component', () => {
|
||||||
transform="translate(0, 0) scale(1)"
|
transform="translate(0, 0) scale(1)"
|
||||||
>
|
>
|
||||||
<g
|
<g
|
||||||
transform="scale(64) translate(0.25, 0.25)"
|
data-testid="tile/xxx/7//"
|
||||||
|
transform="scale(1024) translate(0.25, 0.25)"
|
||||||
/>
|
/>
|
||||||
<g
|
<g
|
||||||
transform="scale(128) translate(0.5, 0.5)"
|
data-testid="tile/xxx/8//"
|
||||||
|
transform="scale(512) translate(0.5, 0.5)"
|
||||||
/>
|
/>
|
||||||
<g
|
<g
|
||||||
transform="scale(2048) translate(0, 0)"
|
data-testid="tile/xxx/11//"
|
||||||
|
transform="scale(64) translate(0, 0)"
|
||||||
/>
|
/>
|
||||||
<g
|
<g
|
||||||
transform="scale(1024) translate(0, 0)"
|
data-testid="tile/xxx/10//"
|
||||||
|
transform="scale(128) translate(0, 0)"
|
||||||
/>
|
/>
|
||||||
<g
|
<g
|
||||||
|
data-testid="tile/xxx/9//"
|
||||||
transform="scale(256) translate(0, 0)"
|
transform="scale(256) translate(0, 0)"
|
||||||
>
|
>
|
||||||
<g
|
<g
|
||||||
|
@ -259,6 +265,636 @@ describe('The LayerStack component', () => {
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('generates two empty layers and a populated one', () => {
|
||||||
|
// const { result } = renderHook(() => useAtom(tiledLayersAtom));
|
||||||
|
render(
|
||||||
|
<LayerStack
|
||||||
|
numberOfTiledLayers={3}
|
||||||
|
keyObject={{ provider: 'xxx', zoomLevel: 9, x: 777, y: 333 }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const svg = screen.getByTestId('layer-stack');
|
||||||
|
expect(svg).toMatchInlineSnapshot(`
|
||||||
|
<svg
|
||||||
|
data-testid="layer-stack"
|
||||||
|
height="768"
|
||||||
|
width="1024"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 0) scale(1)"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
data-testid="tile/xxx/8//"
|
||||||
|
transform="scale(512) translate(0.5, 0.5)"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
data-testid="tile/xxx/10//"
|
||||||
|
transform="scale(128) translate(0, 0)"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
data-testid="tile/xxx/9//"
|
||||||
|
transform="scale(256) translate(0, 0)"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('populates a new layer when zoomed in', () => {
|
||||||
|
// const { result } = renderHook(() => useAtom(tiledLayersAtom));
|
||||||
|
render(
|
||||||
|
<LayerStack
|
||||||
|
numberOfTiledLayers={3}
|
||||||
|
keyObject={{ provider: 'xxx', zoomLevel: 9, x: 777, y: 333 }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const { result } = renderHook(() => [
|
||||||
|
useAtom(coordinateSystemAtom),
|
||||||
|
useAtom(relativeCoordinateSystemAtom),
|
||||||
|
]);
|
||||||
|
act(() => {
|
||||||
|
result.current[0][1]({
|
||||||
|
shift: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
zoom: 1,
|
||||||
|
} as any);
|
||||||
|
result.current[1][1]({
|
||||||
|
deltaShift: null,
|
||||||
|
zoomCenter: { x: 0, y: 0 },
|
||||||
|
deltaZoom: 2,
|
||||||
|
} as any);
|
||||||
|
});
|
||||||
|
const svg = screen.getByTestId('layer-stack');
|
||||||
|
expect(svg).toMatchInlineSnapshot(`
|
||||||
|
<svg
|
||||||
|
data-testid="layer-stack"
|
||||||
|
height="768"
|
||||||
|
width="1024"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 0) scale(2)"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
data-testid="tile/xxx/8//"
|
||||||
|
transform="scale(512) translate(0.5, 0.5)"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
data-testid="tile/xxx/9//"
|
||||||
|
transform="scale(256) translate(0, 0)"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/333.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/334.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/335.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/777/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/778/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/779/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/780/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(4, 3)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/9/781/336.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
data-testid="tile/xxx/10//"
|
||||||
|
transform="scale(128) translate(0, 0)"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1554/666.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1555/666.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 0)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1556/666.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1554/667.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1555/667.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 1)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1556/667.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1554/668.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1555/668.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 2)"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<image
|
||||||
|
height="1"
|
||||||
|
href="https://tile.openstreetmap.org/10/1556/668.png"
|
||||||
|
width="1"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,8 +47,13 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
||||||
const numberOfTiledLayers =
|
const numberOfTiledLayers =
|
||||||
props.numberOfTiledLayers === undefined ? 1 : props.numberOfTiledLayers;
|
props.numberOfTiledLayers === undefined ? 1 : props.numberOfTiledLayers;
|
||||||
|
|
||||||
const [activeTiledLayer, setActiveTiledLayer] = useState(
|
const activeTiledLayer = Math.min(
|
||||||
Math.floor(numberOfTiledLayers / 2)
|
Math.max(
|
||||||
|
Math.round(Math.log2(coordinateSystem.zoom)) +
|
||||||
|
Math.floor(numberOfTiledLayers / 2),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
numberOfTiledLayers - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewPort = {
|
const viewPort = {
|
||||||
|
@ -71,7 +76,7 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTiledLayer = (i: number) => {
|
const getTiledLayer = (i: number) => {
|
||||||
const relativeZoomLevel = i - activeTiledLayer;
|
const relativeZoomLevel = i - Math.floor(numberOfTiledLayers / 2);
|
||||||
const zoom = 2 ** relativeZoomLevel;
|
const zoom = 2 ** relativeZoomLevel;
|
||||||
const origin = {
|
const origin = {
|
||||||
x: props.keyObject.x * zoom,
|
x: props.keyObject.x * zoom,
|
||||||
|
@ -87,15 +92,19 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
||||||
x: origin.x - floor(origin.x),
|
x: origin.x - floor(origin.x),
|
||||||
y: origin.y - floor(origin.y),
|
y: origin.y - floor(origin.y),
|
||||||
};
|
};
|
||||||
|
const key = tileUri({
|
||||||
|
provider: keyObject.provider,
|
||||||
|
zoomLevel: keyObject.zoomLevel,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
transform={`scale(${256 * zoom}) translate(${shift.x}, ${shift.y})`}
|
transform={`scale(${256 / zoom}) translate(${shift.x}, ${shift.y})`}
|
||||||
key={tileUri({
|
key={key}
|
||||||
provider: keyObject.provider,
|
data-testid={key}
|
||||||
zoomLevel: keyObject.zoomLevel,
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
<TiledLayer
|
<TiledLayer
|
||||||
|
key={key}
|
||||||
keyObject={keyObject}
|
keyObject={keyObject}
|
||||||
viewPort={i === activeTiledLayer ? viewPort : undefined}
|
viewPort={i === activeTiledLayer ? viewPort : undefined}
|
||||||
tileFactory={simpleTileFactory}
|
tileFactory={simpleTileFactory}
|
||||||
|
@ -104,8 +113,6 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const tileLayers = range(0, numberOfTiledLayers).map((i) => {});
|
|
||||||
|
|
||||||
// console.log(`tiledLayers: ${JSON.stringify(tiledLayers)}`);
|
// console.log(`tiledLayers: ${JSON.stringify(tiledLayers)}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -123,7 +130,7 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Tiled layers with more details
|
// Tiled layers with more details
|
||||||
range(numberOfTiledLayers, activeTiledLayer + 1, -1).map(
|
range(numberOfTiledLayers - 1, activeTiledLayer, -1).map(
|
||||||
getTiledLayer
|
getTiledLayer
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ export const Tile: react.FC<TileProperties> = memo((props: TileProperties) => {
|
||||||
const timeout = (ms: number) => {
|
const timeout = (ms: number) => {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
};
|
};
|
||||||
console.log(`Rendering tile: ${props.href}`);
|
// console.log(`Rendering tile: ${props.href}`);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadImage = async () => {
|
const loadImage = async () => {
|
||||||
console.log(`Pre loading: ${props.href}`);
|
// console.log(`Pre loading: ${props.href}`);
|
||||||
const image = new Image(1, 1);
|
const image = new Image(1, 1);
|
||||||
image.loading = 'eager';
|
image.loading = 'eager';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -7,6 +7,10 @@ const fakeTileFactory: TileFactory = (keyObject) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
describe('The TiledLayer component ', () => {
|
describe('The TiledLayer component ', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
globalThis.cacheForTiledLayer = new Map();
|
||||||
|
});
|
||||||
|
|
||||||
test('exposes the tiles needed per its viewport', () => {
|
test('exposes the tiles needed per its viewport', () => {
|
||||||
const { baseElement } = render(
|
const { baseElement } = render(
|
||||||
<svg>
|
<svg>
|
||||||
|
@ -133,7 +137,7 @@ describe('The TiledLayer component ', () => {
|
||||||
rerender(
|
rerender(
|
||||||
<svg>
|
<svg>
|
||||||
<TiledLayer
|
<TiledLayer
|
||||||
keyObject={{ provider: 'osm', zoomLevel: 11, x: 5, y: 8 }}
|
keyObject={{ provider: 'osm', zoomLevel: 10, x: 4, y: 10 }}
|
||||||
viewPort={{ topLeft: { x: 5, y: 0 }, bottomRight: { x: 5, y: 2 } }}
|
viewPort={{ topLeft: { x: 5, y: 0 }, bottomRight: { x: 5, y: 2 } }}
|
||||||
tileFactory={fakeTileFactory}
|
tileFactory={fakeTileFactory}
|
||||||
/>
|
/>
|
||||||
|
@ -169,21 +173,21 @@ describe('The TiledLayer component ', () => {
|
||||||
transform="translate(5, 0)"
|
transform="translate(5, 0)"
|
||||||
>
|
>
|
||||||
<text>
|
<text>
|
||||||
{"provider":"osm","zoomLevel":11,"x":10,"y":8}
|
{"provider":"osm","zoomLevel":10,"x":9,"y":10}
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
<g
|
<g
|
||||||
transform="translate(5, 1)"
|
transform="translate(5, 1)"
|
||||||
>
|
>
|
||||||
<text>
|
<text>
|
||||||
{"provider":"osm","zoomLevel":11,"x":10,"y":9}
|
{"provider":"osm","zoomLevel":10,"x":9,"y":11}
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
<g
|
<g
|
||||||
transform="translate(5, 2)"
|
transform="translate(5, 2)"
|
||||||
>
|
>
|
||||||
<text>
|
<text>
|
||||||
{"provider":"osm","zoomLevel":11,"x":10,"y":10}
|
{"provider":"osm","zoomLevel":10,"x":9,"y":12}
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -267,5 +271,4 @@ describe('The TiledLayer component ', () => {
|
||||||
</body>
|
</body>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,26 @@ import { range, isEqual } from 'lodash';
|
||||||
import { Rectangle, TileFactory, TileKeyObject } from './types';
|
import { Rectangle, TileFactory, TileKeyObject } from './types';
|
||||||
import tileUri from './uris';
|
import tileUri from './uris';
|
||||||
|
|
||||||
|
export const thisIsAModule = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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: housekeeping
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
declare global {
|
||||||
|
var cacheForTiledLayer: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
|
|
||||||
|
globalThis.cacheForTiledLayer = new Map();
|
||||||
|
|
||||||
export interface TiledLayerProperties {
|
export interface TiledLayerProperties {
|
||||||
/** The key of the first (ie top/left) tile */
|
/** The key of the first (ie top/left) tile */
|
||||||
keyObject: TileKeyObject;
|
keyObject: TileKeyObject;
|
||||||
|
@ -29,45 +49,46 @@ export interface TiledLayerProperties {
|
||||||
* TODO: remove tileFactory to facilitate memoisation.
|
* TODO: remove tileFactory to facilitate memoisation.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
export const TiledLayer: react.FC<TiledLayerProperties> = (
|
||||||
(props: TiledLayerProperties) => {
|
props: TiledLayerProperties
|
||||||
console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
) => {
|
||||||
const tiles = useRef<any>(new Map());
|
// console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
||||||
|
|
||||||
if (props.viewPort !== undefined) {
|
const key = tileUri({
|
||||||
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).forEach(
|
provider: props.keyObject.provider,
|
||||||
(row) => {
|
zoomLevel: props.keyObject.zoomLevel,
|
||||||
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.current.has(key)) {
|
|
||||||
tiles.current.set(
|
|
||||||
key,
|
|
||||||
<g key={key} transform={`translate(${col}, ${row})`}>
|
|
||||||
{props.tileFactory(keyObject)}
|
|
||||||
</g>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>{Array.from(tiles.current.values())}</>;
|
const tiles: any = globalThis.cacheForTiledLayer.get(key) ?? new Map();
|
||||||
},
|
if (props.viewPort !== undefined) {
|
||||||
(prevProps, nextProps) =>
|
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).forEach(
|
||||||
isEqual(
|
(row) => {
|
||||||
[prevProps.keyObject, prevProps.viewPort],
|
range(
|
||||||
[nextProps.keyObject, nextProps.viewPort]
|
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,
|
||||||
|
<g key={key} transform={`translate(${col}, ${row})`}>
|
||||||
|
{props.tileFactory(keyObject)}
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
globalThis.cacheForTiledLayer.set(key, tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{Array.from(tiles.values())}</>;
|
||||||
|
};
|
||||||
|
|
||||||
export default TiledLayer;
|
export default TiledLayer;
|
||||||
|
|
Loading…
Reference in New Issue