Handling window resize (and rotate).

This commit is contained in:
Eric van der Vlist 2022-11-02 15:14:34 +01:00
parent 7811f00779
commit 61fc42b251
6 changed files with 63 additions and 59 deletions

View File

@ -26,6 +26,7 @@
"jotai": "^1.8.6",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-cool-dimensions": "^2.0.7",
"react-dom": "^18.2.0",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",

View File

@ -1,15 +1,12 @@
import { Redirect, Route } from 'react-router-dom';
import {
IonApp,
IonButtons,
IonContent,
IonFooter,
IonHeader,
IonRouterOutlet,
IonToolbar,
setupIonicReact,
} from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';

View File

@ -79,11 +79,7 @@ export const LayerStack: react.FC<LayerStackProperties> = (
// console.log(`tiledLayers: ${JSON.stringify(tiledLayers)}`);
return (
<svg
width={window.innerWidth}
height={window.innerHeight}
data-testid='layer-stack'
>
<svg width='100%' height='100%' data-testid='layer-stack'>
<g
transform={`translate(${props.coordinateSystem.shift.x}, ${props.coordinateSystem.shift.y}) scale(${props.coordinateSystem.zoom})`}
>

View File

@ -1,4 +1,6 @@
import react, { useEffect, useState } from 'react';
import useDimensions from 'react-cool-dimensions';
import { MapScope, Point } from './types';
import Map from './Map';
import Handlers from './Handlers';
@ -58,6 +60,7 @@ export const LiveMap: react.FC<LiveMapProperties> = (
setScope(props.scope);
}, [props.scope]);
console.log(`LiveMap rendering: ${JSON.stringify(scope)}`);
const { observe, width, height } = useDimensions<HTMLDivElement>();
const transform = (t: Transformation) => {
const deltaZoom = t.deltaZoom === null ? 1 : t.deltaZoom;
const deltaZoomLevel = Math.log2(deltaZoom);
@ -96,12 +99,12 @@ export const LiveMap: react.FC<LiveMapProperties> = (
x:
tilesCenter.x -
actualDeltaShiftTiles.x -
(window.innerWidth / 2 / visibleTileSize - actualZoomCenterTiles.x) *
(width / 2 / visibleTileSize - actualZoomCenterTiles.x) *
(deltaZoom - 1),
y:
tilesCenter.y -
actualDeltaShiftTiles.y -
(window.innerHeight / 2 / visibleTileSize - actualZoomCenterTiles.y) *
(height / 2 / visibleTileSize - actualZoomCenterTiles.y) *
(deltaZoom - 1),
};
@ -127,10 +130,10 @@ export const LiveMap: react.FC<LiveMapProperties> = (
};
return (
<>
<div style={{ width: '100%', height: '100%' }} ref={observe}>
<Handlers transformMap={transform} />
<Map scope={scope} numberOfTiledLayers={props.numberOfTiledLayers} />
</>
</div>
);
};

View File

@ -1,4 +1,5 @@
import react from 'react';
import useDimensions from 'react-cool-dimensions';
import { Point, MapScope } from './types';
import LayerStack from './LayerStack';
@ -13,13 +14,15 @@ export interface MapProperties {
/**
*
* @returns A `<Map>` component
*
*
* `<Map>` components display the map specified by their {@link MapProperties}'s scope.
*
* They can be driven by {@link components/map/LiveMap!LiveMap} component to react to user's event.
*
* They can be driven by {@link components/map/LiveMap!LiveMap} component to react to user's event.
*
*/
export const Map: react.FC<MapProperties> = (props: MapProperties) => {
const { observe, width, height } = useDimensions<HTMLDivElement>();
const tileProvider = tileProviders[props.scope.tileProvider];
const tilesZoom = Math.min(
@ -33,13 +36,13 @@ export const Map: react.FC<MapProperties> = (props: MapProperties) => {
const softZoom = props.scope.zoom - tilesZoom;
const relativeScale = 2 ** softZoom;
const visibleTileSize = tileProvider.tileSize * relativeScale;
const nbTilesLeft = window.innerWidth / 2 / visibleTileSize;
const nbTilesTop = window.innerHeight / 2 / visibleTileSize;
const nbTilesLeft = width / 2 / visibleTileSize;
const nbTilesTop = height / 2 / visibleTileSize;
const firstTileLeft = Math.floor(tilesCenter.x - nbTilesLeft);
const firstTileTop = Math.floor(tilesCenter.y - nbTilesTop);
return (
<>
<div style={{ width: '100%', height: '100%' }} ref={observe}>
<LayerStack
numberOfTiledLayers={props.numberOfTiledLayers}
keyObject={{
@ -56,7 +59,7 @@ export const Map: react.FC<MapProperties> = (props: MapProperties) => {
zoom: relativeScale,
}}
/>
</>
</div>
);
};

View File

@ -1,4 +1,4 @@
import react from 'react';
import react, { useRef } from 'react';
import TileSet from './TileSet';
import { Point, TileKeyObject } from './types';
import { CoordinateSystem } from './LiveMap';
@ -32,48 +32,52 @@ export interface TiledLayerProperties {
export const TiledLayer: react.FC<TiledLayerProperties> = (
props: TiledLayerProperties
) => {
const viewPort =
props.zoom === 256
? {
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 + window.innerWidth) /
props.coordinateSystem.zoom /
256
) -
1,
y:
props.keyObject.y +
Math.ceil(
(-props.coordinateSystem.shift.y + window.innerHeight) /
props.coordinateSystem.zoom /
256
) -
1,
},
}
: undefined;
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,
},
};
}
return (
<g
transform={`scale(${props.zoom}) translate(${props.shift.x}, ${props.shift.y})`}
ref={g}
>
<TileSet
keyObject={{