Moving the underlying map out of the slippy component and handling window resize events.
This commit is contained in:
parent
2207ae1652
commit
75b4bb2e2b
14
README.md
14
README.md
|
@ -1,3 +1,15 @@
|
|||
# Dyomedea
|
||||
|
||||
Application de randonnée
|
||||
## Hiking app.
|
||||
|
||||
## Components
|
||||
|
||||
### Slippy
|
||||
|
||||
The viewport on the underlying map
|
||||
|
||||
### Map
|
||||
|
||||
The map itself (and its overlays)
|
||||
|
||||
|
||||
|
|
|
@ -21,14 +21,20 @@ import '@ionic/react/css/display.css';
|
|||
/* Theme variables */
|
||||
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();
|
||||
|
||||
const App: React.FC = () => (
|
||||
<IonApp>
|
||||
<Provider store={store}>
|
||||
<Slippy />
|
||||
<Layer>
|
||||
<Map />
|
||||
</Layer>
|
||||
</Provider>
|
||||
</IonApp>
|
||||
);
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -1,12 +1,12 @@
|
|||
import react from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import MouseHandler from './mouse-handler';
|
||||
import Layer from './layer';
|
||||
|
||||
import '../../theme/slippy.css';
|
||||
import SingleTouchHandler from './single-touch-handler';
|
||||
import DoubleTouchHandler from './double-touch-handler';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { MapState } from '../../store/map';
|
||||
|
||||
export interface Point {
|
||||
x: number;
|
||||
|
@ -24,19 +24,25 @@ export interface Scale {
|
|||
};
|
||||
}
|
||||
|
||||
interface ViewportProps {
|
||||
children: any;
|
||||
}
|
||||
|
||||
const Slippy: react.FC<ViewportProps> = (props: ViewportProps) => {
|
||||
const Slippy: react.FC<{}> = () => {
|
||||
//console.log(`--- Rendering viewport, props: ${JSON.stringify(props)} ---`);
|
||||
|
||||
const viewport = useSelector(
|
||||
(state: { map: MapState }) => state.map.viewport
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='slippy'>
|
||||
<MouseHandler>
|
||||
<SingleTouchHandler>
|
||||
<DoubleTouchHandler>
|
||||
<Layer>{props.children}</Layer>
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
width: viewport.width + 'px',
|
||||
height: viewport.height + 'px',
|
||||
}}
|
||||
/>
|
||||
</DoubleTouchHandler>
|
||||
</SingleTouchHandler>
|
||||
</MouseHandler>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import react, { useCallback, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import react, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { configureStore } from '@reduxjs/toolkit';
|
||||
|
||||
import slippyReducer from './slippy';
|
||||
import mapReducer from './map';
|
||||
|
||||
const store = configureStore({
|
||||
reducer: { slippy: slippyReducer},
|
||||
reducer: { slippy: slippyReducer, map: mapReducer },
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
|
|
@ -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;
|
|
@ -4,8 +4,6 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 4032px;
|
||||
height: 2268px;
|
||||
}
|
||||
|
||||
.huge {
|
||||
position: fixed;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue