diff --git a/package.json b/package.json index 3a191c7..88f891b 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/App.tsx b/src/App.tsx index d5be32c..6f62f71 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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'; diff --git a/src/components/map/LayerStack.tsx b/src/components/map/LayerStack.tsx index 25d07bd..e598dbf 100644 --- a/src/components/map/LayerStack.tsx +++ b/src/components/map/LayerStack.tsx @@ -79,11 +79,7 @@ export const LayerStack: react.FC = ( // console.log(`tiledLayers: ${JSON.stringify(tiledLayers)}`); return ( - + diff --git a/src/components/map/LiveMap.tsx b/src/components/map/LiveMap.tsx index 6f64a7a..9bd9876 100644 --- a/src/components/map/LiveMap.tsx +++ b/src/components/map/LiveMap.tsx @@ -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 = ( setScope(props.scope); }, [props.scope]); console.log(`LiveMap rendering: ${JSON.stringify(scope)}`); + const { observe, width, height } = useDimensions(); 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 = ( 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 = ( }; return ( - <> +
- +
); }; diff --git a/src/components/map/Map.tsx b/src/components/map/Map.tsx index f39d2b8..0e20ae9 100644 --- a/src/components/map/Map.tsx +++ b/src/components/map/Map.tsx @@ -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 `` component - * + * * `` 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 = (props: MapProperties) => { + const { observe, width, height } = useDimensions(); + const tileProvider = tileProviders[props.scope.tileProvider]; const tilesZoom = Math.min( @@ -33,13 +36,13 @@ export const Map: react.FC = (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 ( - <> +
= (props: MapProperties) => { zoom: relativeScale, }} /> - +
); }; diff --git a/src/components/map/TiledLayer.tsx b/src/components/map/TiledLayer.tsx index e2a28a2..2b58266 100644 --- a/src/components/map/TiledLayer.tsx +++ b/src/components/map/TiledLayer.tsx @@ -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 = ( 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(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 (