Moving the underlying map out of the slippy component and handling window resize events.

This commit is contained in:
Eric van der Vlist 2022-09-12 15:10:12 +02:00
parent 2207ae1652
commit 75b4bb2e2b
9 changed files with 184 additions and 113 deletions

View File

@ -1,3 +1,15 @@
# Dyomedea # Dyomedea
Application de randonnée ## Hiking app.
## Components
### Slippy
The viewport on the underlying map
### Map
The map itself (and its overlays)

View File

@ -21,14 +21,20 @@ import '@ionic/react/css/display.css';
/* Theme variables */ /* Theme variables */
import './theme/variables.css'; import './theme/variables.css';
import Map from './components/map'; import Map from './components/map/map';
import Slippy from './components/slippy';
import Layer from './components/slippy/layer';
import { Fragment } from 'react';
setupIonicReact(); setupIonicReact();
const App: React.FC = () => ( const App: React.FC = () => (
<IonApp> <IonApp>
<Provider store={store}> <Provider store={store}>
<Slippy />
<Layer>
<Map /> <Map />
</Layer>
</Provider> </Provider>
</IonApp> </IonApp>
); );

View File

@ -1,91 +0,0 @@
import react from 'react';
import Slippy from './slippy/index';
const Map: react.FC<{}> = (props: {}) => {
return (
<Slippy>
<div>
<div style={{ height: '256px' }}>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11720/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11721/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11722/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11723/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
</div>
<div style={{ height: '256px' }}>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11720/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11721/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11722/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11723/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
</div>
<div style={{ height: '256px' }}>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11720/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11721/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11722/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11723/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
</div>
</div>
</Slippy>
);
};
export default Map;

109
src/components/map/map.tsx Normal file
View File

@ -0,0 +1,109 @@
import react, { useMemo, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import _ from 'lodash';
import { MapState, mapActions } from '../../store/map';
const Map: react.FC<{}> = (props: {}) => {
const dispatch = useDispatch();
const mapState = useSelector((state: { map: MapState }) => state.map);
console.log(`mapState: ${JSON.stringify(mapState)}`);
const resizeHandler = () => {
dispatch(mapActions.resize());
};
const debouncedResizeHandler = useMemo(
() => _.debounce(resizeHandler, 500),
[]
);
useEffect(() => {
window.addEventListener('resize', debouncedResizeHandler);
}, []);
return (
<div>
<div style={{ height: '256px' }}>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11720/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11721/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11722/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11723/10052.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
</div>
<div style={{ height: '256px' }}>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11720/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11721/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11722/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11723/10053.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
</div>
<div style={{ height: '256px' }}>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11720/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11721/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11722/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
<img
alt=''
role='presentation'
src='https://tile.openstreetmap.org/14/11723/10054.png'
style={{ width: '256px', height: '256px', opacity: 1 }}
/>
</div>
</div>
);
};
export default Map;

View File

@ -1,12 +1,12 @@
import react from 'react'; import react from 'react';
import { useSelector } from 'react-redux';
import MouseHandler from './mouse-handler'; import MouseHandler from './mouse-handler';
import Layer from './layer';
import '../../theme/slippy.css'; import '../../theme/slippy.css';
import SingleTouchHandler from './single-touch-handler'; import SingleTouchHandler from './single-touch-handler';
import DoubleTouchHandler from './double-touch-handler'; import DoubleTouchHandler from './double-touch-handler';
import { useSelector } from 'react-redux';
import { MapState } from '../../store/map';
export interface Point { export interface Point {
x: number; x: number;
@ -24,19 +24,25 @@ export interface Scale {
}; };
} }
interface ViewportProps { const Slippy: react.FC<{}> = () => {
children: any;
}
const Slippy: react.FC<ViewportProps> = (props: ViewportProps) => {
//console.log(`--- Rendering viewport, props: ${JSON.stringify(props)} ---`); //console.log(`--- Rendering viewport, props: ${JSON.stringify(props)} ---`);
const viewport = useSelector(
(state: { map: MapState }) => state.map.viewport
);
return ( return (
<div className='slippy'> <div className='slippy'>
<MouseHandler> <MouseHandler>
<SingleTouchHandler> <SingleTouchHandler>
<DoubleTouchHandler> <DoubleTouchHandler>
<Layer>{props.children}</Layer> <div
style={{
position: 'fixed',
width: viewport.width + 'px',
height: viewport.height + 'px',
}}
/>
</DoubleTouchHandler> </DoubleTouchHandler>
</SingleTouchHandler> </SingleTouchHandler>
</MouseHandler> </MouseHandler>

View File

@ -1,5 +1,5 @@
import react, { useCallback, useState } from 'react'; import react, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import _ from 'lodash'; import _ from 'lodash';

View File

@ -1,9 +1,10 @@
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import slippyReducer from './slippy'; import slippyReducer from './slippy';
import mapReducer from './map';
const store = configureStore({ const store = configureStore({
reducer: { slippy: slippyReducer}, reducer: { slippy: slippyReducer, map: mapReducer },
}); });
export default store; export default store;

30
src/store/map.ts Normal file
View File

@ -0,0 +1,30 @@
import { createSlice } from '@reduxjs/toolkit';
export interface MapState {
viewport: {
width: number;
height: number;
};
}
const initialMapState: MapState = {
viewport: {
width: window.innerWidth,
height: window.innerHeight,
},
};
const mapSlice = createSlice({
name: 'map',
initialState: initialMapState,
reducers: {
resize: (state) => {
state.viewport.height = window.innerHeight;
state.viewport.width = window.innerWidth;
},
},
});
export const mapActions = mapSlice.actions;
export default mapSlice.reducer;

View File

@ -4,8 +4,6 @@
height: 100%; height: 100%;
} }
.background img { .huge {
width: 4032px; position: fixed;
height: 2268px;
} }