Handling window resize (and rotate).
This commit is contained in:
parent
7811f00779
commit
61fc42b251
|
@ -26,6 +26,7 @@
|
||||||
"jotai": "^1.8.6",
|
"jotai": "^1.8.6",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-cool-dimensions": "^2.0.7",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router": "^5.2.0",
|
"react-router": "^5.2.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import { Redirect, Route } from 'react-router-dom';
|
|
||||||
import {
|
import {
|
||||||
IonApp,
|
IonApp,
|
||||||
IonButtons,
|
IonButtons,
|
||||||
IonContent,
|
IonContent,
|
||||||
IonFooter,
|
IonFooter,
|
||||||
IonHeader,
|
IonHeader,
|
||||||
IonRouterOutlet,
|
|
||||||
IonToolbar,
|
IonToolbar,
|
||||||
setupIonicReact,
|
setupIonicReact,
|
||||||
} from '@ionic/react';
|
} from '@ionic/react';
|
||||||
import { IonReactRouter } from '@ionic/react-router';
|
|
||||||
|
|
||||||
/* Core CSS required for Ionic components to work properly */
|
/* Core CSS required for Ionic components to work properly */
|
||||||
import '@ionic/react/css/core.css';
|
import '@ionic/react/css/core.css';
|
||||||
|
|
|
@ -79,11 +79,7 @@ export const LayerStack: react.FC<LayerStackProperties> = (
|
||||||
// console.log(`tiledLayers: ${JSON.stringify(tiledLayers)}`);
|
// console.log(`tiledLayers: ${JSON.stringify(tiledLayers)}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg width='100%' height='100%' data-testid='layer-stack'>
|
||||||
width={window.innerWidth}
|
|
||||||
height={window.innerHeight}
|
|
||||||
data-testid='layer-stack'
|
|
||||||
>
|
|
||||||
<g
|
<g
|
||||||
transform={`translate(${props.coordinateSystem.shift.x}, ${props.coordinateSystem.shift.y}) scale(${props.coordinateSystem.zoom})`}
|
transform={`translate(${props.coordinateSystem.shift.x}, ${props.coordinateSystem.shift.y}) scale(${props.coordinateSystem.zoom})`}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import react, { useEffect, useState } from 'react';
|
import react, { useEffect, useState } from 'react';
|
||||||
|
import useDimensions from 'react-cool-dimensions';
|
||||||
|
|
||||||
import { MapScope, Point } from './types';
|
import { MapScope, Point } from './types';
|
||||||
import Map from './Map';
|
import Map from './Map';
|
||||||
import Handlers from './Handlers';
|
import Handlers from './Handlers';
|
||||||
|
@ -58,6 +60,7 @@ export const LiveMap: react.FC<LiveMapProperties> = (
|
||||||
setScope(props.scope);
|
setScope(props.scope);
|
||||||
}, [props.scope]);
|
}, [props.scope]);
|
||||||
console.log(`LiveMap rendering: ${JSON.stringify(scope)}`);
|
console.log(`LiveMap rendering: ${JSON.stringify(scope)}`);
|
||||||
|
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;
|
||||||
const deltaZoomLevel = Math.log2(deltaZoom);
|
const deltaZoomLevel = Math.log2(deltaZoom);
|
||||||
|
@ -96,12 +99,12 @@ export const LiveMap: react.FC<LiveMapProperties> = (
|
||||||
x:
|
x:
|
||||||
tilesCenter.x -
|
tilesCenter.x -
|
||||||
actualDeltaShiftTiles.x -
|
actualDeltaShiftTiles.x -
|
||||||
(window.innerWidth / 2 / visibleTileSize - actualZoomCenterTiles.x) *
|
(width / 2 / visibleTileSize - actualZoomCenterTiles.x) *
|
||||||
(deltaZoom - 1),
|
(deltaZoom - 1),
|
||||||
y:
|
y:
|
||||||
tilesCenter.y -
|
tilesCenter.y -
|
||||||
actualDeltaShiftTiles.y -
|
actualDeltaShiftTiles.y -
|
||||||
(window.innerHeight / 2 / visibleTileSize - actualZoomCenterTiles.y) *
|
(height / 2 / visibleTileSize - actualZoomCenterTiles.y) *
|
||||||
(deltaZoom - 1),
|
(deltaZoom - 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,10 +130,10 @@ export const LiveMap: react.FC<LiveMapProperties> = (
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ width: '100%', height: '100%' }} ref={observe}>
|
||||||
<Handlers transformMap={transform} />
|
<Handlers transformMap={transform} />
|
||||||
<Map scope={scope} numberOfTiledLayers={props.numberOfTiledLayers} />
|
<Map scope={scope} numberOfTiledLayers={props.numberOfTiledLayers} />
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import react from 'react';
|
import react from 'react';
|
||||||
|
import useDimensions from 'react-cool-dimensions';
|
||||||
|
|
||||||
import { Point, MapScope } from './types';
|
import { Point, MapScope } from './types';
|
||||||
import LayerStack from './LayerStack';
|
import LayerStack from './LayerStack';
|
||||||
|
@ -20,6 +21,8 @@ export interface MapProperties {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const Map: react.FC<MapProperties> = (props: MapProperties) => {
|
export const Map: react.FC<MapProperties> = (props: MapProperties) => {
|
||||||
|
const { observe, width, height } = useDimensions<HTMLDivElement>();
|
||||||
|
|
||||||
const tileProvider = tileProviders[props.scope.tileProvider];
|
const tileProvider = tileProviders[props.scope.tileProvider];
|
||||||
|
|
||||||
const tilesZoom = Math.min(
|
const tilesZoom = Math.min(
|
||||||
|
@ -33,13 +36,13 @@ export const Map: react.FC<MapProperties> = (props: MapProperties) => {
|
||||||
const softZoom = props.scope.zoom - tilesZoom;
|
const softZoom = props.scope.zoom - tilesZoom;
|
||||||
const relativeScale = 2 ** softZoom;
|
const relativeScale = 2 ** softZoom;
|
||||||
const visibleTileSize = tileProvider.tileSize * relativeScale;
|
const visibleTileSize = tileProvider.tileSize * relativeScale;
|
||||||
const nbTilesLeft = window.innerWidth / 2 / visibleTileSize;
|
const nbTilesLeft = width / 2 / visibleTileSize;
|
||||||
const nbTilesTop = window.innerHeight / 2 / visibleTileSize;
|
const nbTilesTop = height / 2 / visibleTileSize;
|
||||||
const firstTileLeft = Math.floor(tilesCenter.x - nbTilesLeft);
|
const firstTileLeft = Math.floor(tilesCenter.x - nbTilesLeft);
|
||||||
const firstTileTop = Math.floor(tilesCenter.y - nbTilesTop);
|
const firstTileTop = Math.floor(tilesCenter.y - nbTilesTop);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ width: '100%', height: '100%' }} ref={observe}>
|
||||||
<LayerStack
|
<LayerStack
|
||||||
numberOfTiledLayers={props.numberOfTiledLayers}
|
numberOfTiledLayers={props.numberOfTiledLayers}
|
||||||
keyObject={{
|
keyObject={{
|
||||||
|
@ -56,7 +59,7 @@ export const Map: react.FC<MapProperties> = (props: MapProperties) => {
|
||||||
zoom: relativeScale,
|
zoom: relativeScale,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import react from 'react';
|
import react, { useRef } from 'react';
|
||||||
import TileSet from './TileSet';
|
import TileSet from './TileSet';
|
||||||
import { Point, TileKeyObject } from './types';
|
import { Point, TileKeyObject } from './types';
|
||||||
import { CoordinateSystem } from './LiveMap';
|
import { CoordinateSystem } from './LiveMap';
|
||||||
|
@ -32,30 +32,33 @@ export interface TiledLayerProperties {
|
||||||
export const TiledLayer: react.FC<TiledLayerProperties> = (
|
export const TiledLayer: react.FC<TiledLayerProperties> = (
|
||||||
props: TiledLayerProperties
|
props: TiledLayerProperties
|
||||||
) => {
|
) => {
|
||||||
const viewPort =
|
const g = useRef<SVGGElement>(null);
|
||||||
props.zoom === 256
|
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: {
|
topLeft: {
|
||||||
x:
|
x:
|
||||||
props.keyObject.x +
|
props.keyObject.x +
|
||||||
Math.floor(
|
Math.floor(
|
||||||
-props.coordinateSystem.shift.x /
|
-props.coordinateSystem.shift.x / props.coordinateSystem.zoom / 256
|
||||||
props.coordinateSystem.zoom /
|
|
||||||
256
|
|
||||||
),
|
),
|
||||||
y:
|
y:
|
||||||
props.keyObject.y +
|
props.keyObject.y +
|
||||||
Math.floor(
|
Math.floor(
|
||||||
-props.coordinateSystem.shift.y /
|
-props.coordinateSystem.shift.y / props.coordinateSystem.zoom / 256
|
||||||
props.coordinateSystem.zoom /
|
|
||||||
256
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
bottomRight: {
|
bottomRight: {
|
||||||
x:
|
x:
|
||||||
props.keyObject.x +
|
props.keyObject.x +
|
||||||
Math.ceil(
|
Math.ceil(
|
||||||
(-props.coordinateSystem.shift.x + window.innerWidth) /
|
(-props.coordinateSystem.shift.x + nearerHTMLParent.offsetWidth) /
|
||||||
props.coordinateSystem.zoom /
|
props.coordinateSystem.zoom /
|
||||||
256
|
256
|
||||||
) -
|
) -
|
||||||
|
@ -63,17 +66,18 @@ export const TiledLayer: react.FC<TiledLayerProperties> = (
|
||||||
y:
|
y:
|
||||||
props.keyObject.y +
|
props.keyObject.y +
|
||||||
Math.ceil(
|
Math.ceil(
|
||||||
(-props.coordinateSystem.shift.y + window.innerHeight) /
|
(-props.coordinateSystem.shift.y + nearerHTMLParent.offsetHeight) /
|
||||||
props.coordinateSystem.zoom /
|
props.coordinateSystem.zoom /
|
||||||
256
|
256
|
||||||
) -
|
) -
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
: undefined;
|
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
transform={`scale(${props.zoom}) translate(${props.shift.x}, ${props.shift.y})`}
|
transform={`scale(${props.zoom}) translate(${props.shift.x}, ${props.shift.y})`}
|
||||||
|
ref={g}
|
||||||
>
|
>
|
||||||
<TileSet
|
<TileSet
|
||||||
keyObject={{
|
keyObject={{
|
||||||
|
|
Loading…
Reference in New Issue