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 props: CurrentLocationProperties
) => { ) => {
const [location] = useAtom(locationAtom); const [location] = useAtom(locationAtom);
console.log(
`Rendering CurrentLocation, location:${JSON.stringify(location)}`
);
return location !== null ? ( return location !== null ? (
<Marker <Marker
key='currentLocation' key='currentLocation'

View File

@ -48,6 +48,12 @@ export interface LayerStackProperties {
export const LayerStack: react.FC<LayerStackProperties> = ( export const LayerStack: react.FC<LayerStackProperties> = (
props: LayerStackProperties props: LayerStackProperties
) => { ) => {
console.log(
`LayerStack rendering, coordinateSystem: ${JSON.stringify(
props.coordinateSystem
)}, slippyGraphics: ${props.slippyGraphics}`
);
const numberOfTiledLayers = const numberOfTiledLayers =
props.numberOfTiledLayers === undefined ? 1 : props.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 useDimensions from 'react-cool-dimensions';
import { MapScope, Point } from './types'; import { MapScope, Point } from './types';
@ -61,7 +66,11 @@ export const LiveMap: react.FC<LiveMapProperties> = (
useEffect(() => { useEffect(() => {
setScope(props.scope); setScope(props.scope);
}, [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 { observe, width, height } = useDimensions<HTMLDivElement>();
const transform = (t: Transformation) => { const transform = (t: Transformation) => {
const deltaZoom = t.deltaZoom === null ? 1 : t.deltaZoom; 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) => { 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 { observe, width, height } = useDimensions<HTMLDivElement>();
const tileProvider = tileProviders[props.scope.tileProvider]; const tileProvider = tileProviders[props.scope.tileProvider];

View File

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

View File

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