Fixing a bug (the `<g>` element wasn't always available as ref.current in TiledLayer), using a useEffect seems to do the trick.

This commit is contained in:
Eric van der Vlist 2022-11-03 22:20:14 +01:00
parent 84e1ece691
commit 74dbff2d23
6 changed files with 99 additions and 49 deletions

View File

@ -16,6 +16,10 @@ export const CurrentLocation: react.FC<CurrentLocationProperties> = (
props: CurrentLocationProperties
) => {
const [location] = useAtom(locationAtom);
console.log(
`Rendering CurrentLocation, location:${JSON.stringify(location)}`
);
return location !== null ? (
<Marker
key='currentLocation'

View File

@ -48,6 +48,12 @@ export interface LayerStackProperties {
export const LayerStack: react.FC<LayerStackProperties> = (
props: LayerStackProperties
) => {
console.log(
`LayerStack rendering, coordinateSystem: ${JSON.stringify(
props.coordinateSystem
)}, slippyGraphics: ${props.slippyGraphics}`
);
const numberOfTiledLayers =
props.numberOfTiledLayers === undefined ? 1 : props.numberOfTiledLayers;

View File

@ -1,4 +1,9 @@
import react, { JSXElementConstructor, ReactElement, useEffect, useState } from 'react';
import react, {
JSXElementConstructor,
ReactElement,
useEffect,
useState,
} from 'react';
import useDimensions from 'react-cool-dimensions';
import { MapScope, Point } from './types';
@ -61,7 +66,11 @@ export const LiveMap: react.FC<LiveMapProperties> = (
useEffect(() => {
setScope(props.scope);
}, [props.scope]);
console.log(`LiveMap rendering: ${JSON.stringify(scope)}`);
console.log(
`LiveMap rendering, scope: ${JSON.stringify(scope)}, slippyGraphics: ${
props.slippyGraphics
}`
);
const { observe, width, height } = useDimensions<HTMLDivElement>();
const transform = (t: Transformation) => {
const deltaZoom = t.deltaZoom === null ? 1 : t.deltaZoom;

View File

@ -25,6 +25,12 @@ export interface MapProperties {
*
*/
export const Map: react.FC<MapProperties> = (props: MapProperties) => {
console.log(
`Map rendering, scope: ${JSON.stringify(props.scope)}, slippyGraphics: ${
props.slippyGraphics
}`
);
const { observe, width, height } = useDimensions<HTMLDivElement>();
const tileProvider = tileProviders[props.scope.tileProvider];

View File

@ -11,6 +11,8 @@ export interface MarkerProperties {
}
export const Marker: react.FC<MarkerProperties> = (props: MarkerProperties) => {
console.log(`Rendering Marker`);
if (
props.keyObject === undefined ||
props.zoom === undefined ||

View File

@ -2,10 +2,12 @@ import react, {
cloneElement,
JSXElementConstructor,
ReactElement,
useEffect,
useRef,
useState,
} from 'react';
import TileSet from './TileSet';
import { Point, TileKeyObject } from './types';
import { Point, Rectangle, TileKeyObject } from './types';
import { CoordinateSystem } from './LiveMap';
export interface TiledLayerProperties {
@ -40,47 +42,65 @@ export const TiledLayer: react.FC<TiledLayerProperties> = (
props: TiledLayerProperties
) => {
const g = useRef<SVGGElement>(null);
var viewPort: any = undefined;
if (
props.zoom === 256 &&
g.current !== null &&
g.current.ownerSVGElement !== null &&
g.current.ownerSVGElement.parentElement !== null
) {
const nearerHTMLParent = g.current.ownerSVGElement.parentElement;
viewPort = {
topLeft: {
x:
props.keyObject.x +
Math.floor(
-props.coordinateSystem.shift.x / props.coordinateSystem.zoom / 256
),
y:
props.keyObject.y +
Math.floor(
-props.coordinateSystem.shift.y / props.coordinateSystem.zoom / 256
),
},
bottomRight: {
x:
props.keyObject.x +
Math.ceil(
(-props.coordinateSystem.shift.x + nearerHTMLParent.offsetWidth) /
props.coordinateSystem.zoom /
256
) -
1,
y:
props.keyObject.y +
Math.ceil(
(-props.coordinateSystem.shift.y + nearerHTMLParent.offsetHeight) /
props.coordinateSystem.zoom /
256
) -
1,
},
};
}
const [viewPort, setViewPort] = useState<Rectangle>();
useEffect(() => {
console.log(
`TiledLayer zoom: ${props.zoom}, useEffect, g.current: ${g.current}`
);
if (
props.zoom === 256 &&
g.current !== null &&
g.current.ownerSVGElement !== null &&
g.current.ownerSVGElement.parentElement !== null
) {
const nearerHTMLParent = g.current.ownerSVGElement.parentElement;
setViewPort({
topLeft: {
x:
props.keyObject.x +
Math.floor(
-props.coordinateSystem.shift.x /
props.coordinateSystem.zoom /
256
),
y:
props.keyObject.y +
Math.floor(
-props.coordinateSystem.shift.y /
props.coordinateSystem.zoom /
256
),
},
bottomRight: {
x:
props.keyObject.x +
Math.ceil(
(-props.coordinateSystem.shift.x + nearerHTMLParent.offsetWidth) /
props.coordinateSystem.zoom /
256
) -
1,
y:
props.keyObject.y +
Math.ceil(
(-props.coordinateSystem.shift.y +
nearerHTMLParent.offsetHeight) /
props.coordinateSystem.zoom /
256
) -
1,
},
});
}
}, [props]);
console.log(
`Rendering TiledLayer, zoom: ${props.zoom}, viewPort: ${JSON.stringify(
viewPort
)}, slippyGraphics: ${props.slippyGraphics}`
);
return (
<>
<g
@ -96,16 +116,19 @@ export const TiledLayer: react.FC<TiledLayerProperties> = (
}}
viewPort={viewPort}
/>
{props.slippyGraphics !== undefined && viewPort !== undefined
? // Slippy graphics (if needed)
props.slippyGraphics.map((slippyGraphic) =>
{props.slippyGraphics !== undefined && viewPort !== undefined ? (
// Slippy graphics (if needed)
<>
{props.slippyGraphics.map((slippyGraphic) =>
cloneElement(slippyGraphic, {
keyObject: props.keyObject,
zoom: props.coordinateSystem.zoom,
viewPort: viewPort,
})
)
: null}
)}
{console.log('TiledLayer: adding slippyGraphics')},
</>
) : null}
</g>
</>
);