Using maps instead of objects to store tiles and removing the reinititialization when TiledLayer properties are updated.
This commit is contained in:
parent
b5dd10e920
commit
4238ce0938
|
@ -0,0 +1,138 @@
|
||||||
|
import { renderHook, act } from '@testing-library/react';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
|
import { coordinateSystemAtom, relativeCoordinateSystemAtom } from './Map';
|
||||||
|
|
||||||
|
describe('The Map component coordinate system', () => {
|
||||||
|
test('is initialized', () => {
|
||||||
|
const { result } = renderHook(() => useAtom(coordinateSystemAtom));
|
||||||
|
expect(result.current[0]).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"shift": Object {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
"zoom": 1,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reacts to a translation', () => {
|
||||||
|
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: { x: 5, y: 1 },
|
||||||
|
zoomCenter: null,
|
||||||
|
deltaZoom: null,
|
||||||
|
} as any);
|
||||||
|
});
|
||||||
|
expect(result.current[0][0]).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"shift": Object {
|
||||||
|
"x": 5,
|
||||||
|
"y": 1,
|
||||||
|
},
|
||||||
|
"zoom": 1,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reacts to a zoom on its origin', () => {
|
||||||
|
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: null,
|
||||||
|
deltaZoom: 5,
|
||||||
|
} as any);
|
||||||
|
});
|
||||||
|
expect(result.current[0][0]).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"shift": Object {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
},
|
||||||
|
"zoom": 5,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reacts to a zoom around another point', () => {
|
||||||
|
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: 2, y: 2 },
|
||||||
|
deltaZoom: 5,
|
||||||
|
} as any);
|
||||||
|
});
|
||||||
|
expect(result.current[0][0]).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"shift": Object {
|
||||||
|
"x": -8,
|
||||||
|
"y": -8,
|
||||||
|
},
|
||||||
|
"zoom": 5,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reacts to a zoom (around another point) and a translation', () => {
|
||||||
|
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: { x: 1, y: 3 },
|
||||||
|
zoomCenter: { x: 2, y: 2 },
|
||||||
|
deltaZoom: 5,
|
||||||
|
} as any);
|
||||||
|
});
|
||||||
|
expect(result.current[0][0]).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"shift": Object {
|
||||||
|
"x": -7,
|
||||||
|
"y": -5,
|
||||||
|
},
|
||||||
|
"zoom": 5,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
|
@ -120,7 +120,7 @@ describe('The TiledLayer component ', () => {
|
||||||
</body>
|
</body>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
test('is reinitialized if its key isObject updated', () => {
|
test('is not reinitialized if its key isObject updated', () => {
|
||||||
const { baseElement, rerender } = render(
|
const { baseElement, rerender } = render(
|
||||||
<svg>
|
<svg>
|
||||||
<TiledLayer
|
<TiledLayer
|
||||||
|
@ -144,6 +144,27 @@ describe('The TiledLayer component ', () => {
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<svg>
|
<svg>
|
||||||
|
<g
|
||||||
|
transform="translate(1, 2)"
|
||||||
|
>
|
||||||
|
<text>
|
||||||
|
{"provider":"osm","zoomLevel":10,"x":6,"y":10}
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(2, 2)"
|
||||||
|
>
|
||||||
|
<text>
|
||||||
|
{"provider":"osm","zoomLevel":10,"x":7,"y":10}
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(3, 2)"
|
||||||
|
>
|
||||||
|
<text>
|
||||||
|
{"provider":"osm","zoomLevel":10,"x":8,"y":10}
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
<g
|
<g
|
||||||
transform="translate(5, 0)"
|
transform="translate(5, 0)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -30,12 +30,7 @@ export interface TiledLayerProperties {
|
||||||
export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
||||||
(props: TiledLayerProperties) => {
|
(props: TiledLayerProperties) => {
|
||||||
console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
||||||
const tiles = useRef<any>({});
|
const tiles = useRef<any>(new Map());
|
||||||
const previousKeyObject = useRef<TileKeyObject>(props.keyObject);
|
|
||||||
if (!isEqual(props.keyObject, previousKeyObject.current)) {
|
|
||||||
previousKeyObject.current = props.keyObject;
|
|
||||||
tiles.current = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).map(
|
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).map(
|
||||||
(row) => {
|
(row) => {
|
||||||
|
@ -48,8 +43,9 @@ export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
||||||
y: props.keyObject.y + row,
|
y: props.keyObject.y + row,
|
||||||
};
|
};
|
||||||
const key = tileUri(keyObject);
|
const key = tileUri(keyObject);
|
||||||
if (!Object.hasOwn(tiles.current, key)) {
|
if (!tiles.current.has(key)) {
|
||||||
tiles.current[key] = (
|
tiles.current.set(
|
||||||
|
key,
|
||||||
<g key={key} transform={`translate(${col}, ${row})`}>
|
<g key={key} transform={`translate(${col}, ${row})`}>
|
||||||
{props.tileFactory(keyObject)}
|
{props.tileFactory(keyObject)}
|
||||||
</g>
|
</g>
|
||||||
|
@ -60,7 +56,7 @@ export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return <>{Object.values(tiles.current)}</>;
|
return <>{Array.from(tiles.current.values())}</>;
|
||||||
},
|
},
|
||||||
isEqual
|
isEqual
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue