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>
|
||||
`);
|
||||
});
|
||||
test('is reinitialized if its key isObject updated', () => {
|
||||
test('is not reinitialized if its key isObject updated', () => {
|
||||
const { baseElement, rerender } = render(
|
||||
<svg>
|
||||
<TiledLayer
|
||||
|
@ -144,6 +144,27 @@ describe('The TiledLayer component ', () => {
|
|||
<body>
|
||||
<div>
|
||||
<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
|
||||
transform="translate(5, 0)"
|
||||
>
|
||||
|
|
|
@ -30,12 +30,7 @@ export interface TiledLayerProperties {
|
|||
export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
||||
(props: TiledLayerProperties) => {
|
||||
console.log(`Rendering TiledLayer: ${JSON.stringify(props)}`);
|
||||
const tiles = useRef<any>({});
|
||||
const previousKeyObject = useRef<TileKeyObject>(props.keyObject);
|
||||
if (!isEqual(props.keyObject, previousKeyObject.current)) {
|
||||
previousKeyObject.current = props.keyObject;
|
||||
tiles.current = {};
|
||||
}
|
||||
const tiles = useRef<any>(new Map());
|
||||
|
||||
range(props.viewPort.topLeft.y, props.viewPort.bottomRight.y + 1).map(
|
||||
(row) => {
|
||||
|
@ -48,8 +43,9 @@ export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
|||
y: props.keyObject.y + row,
|
||||
};
|
||||
const key = tileUri(keyObject);
|
||||
if (!Object.hasOwn(tiles.current, key)) {
|
||||
tiles.current[key] = (
|
||||
if (!tiles.current.has(key)) {
|
||||
tiles.current.set(
|
||||
key,
|
||||
<g key={key} transform={`translate(${col}, ${row})`}>
|
||||
{props.tileFactory(keyObject)}
|
||||
</g>
|
||||
|
@ -60,7 +56,7 @@ export const TiledLayer: react.FC<TiledLayerProperties> = memo(
|
|||
}
|
||||
);
|
||||
|
||||
return <>{Object.values(tiles.current)}</>;
|
||||
return <>{Array.from(tiles.current.values())}</>;
|
||||
},
|
||||
isEqual
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue