feat: put map page viewport into URL

This commit is contained in:
Paul Bienkowski 2021-11-30 21:36:44 +01:00
parent 9c7b1bc662
commit 15dfb2dc3b

View file

@ -2,13 +2,42 @@ import React from 'react'
import {Page} from 'components' import {Page} from 'components'
import {useConfig, Config} from 'config' import {useConfig, Config} from 'config'
import {useHistory, useLocation} from 'react-router-dom'
import ReactMapGl, {AttributionControl } from 'react-map-gl' import ReactMapGl, {AttributionControl } from 'react-map-gl'
import styles from './MapPage.module.less' import styles from './MapPage.module.less'
import {obsRoads, basemap } from '../mapstyles' import {obsRoads, basemap } from '../mapstyles'
function CustomMapInner({mapSource, config, mode, children}: {mapSource: string, config: Config, mode?: 'roads'}) { function parseHash(v) {
if (!v) return null
const m = v.match(/^#([0-9\.]+)\/([0-9\.]+)\/([0-9\.]+)$/)
if (!m) return null
return {
zoom: Number.parseFloat(m[1]),
latitude: Number.parseFloat(m[2]),
longitude: Number.parseFloat(m[3]),
}
}
const EMPTY_VIEWPORT = {longitude: 0, latitude: 0, zoom: 0}
function buildHash(v) {
return `${v.zoom.toFixed(2)}/${v.latitude}/${v.longitude}`
}
function useViewportFromUrl() {
const history = useHistory()
const location = useLocation()
const value = React.useMemo(() => parseHash(location.hash), [location.hash])
const setter = React.useCallback((v) => {
history.replace({
hash: buildHash(v)
})
}, [history])
return [value || EMPTY_VIEWPORT, setter]
}
function CustomMapInner({viewportFromUrl, mapSource, config, mode, children}: {viewportFromUrl?: boolean, mapSource: string, config: Config, mode?: 'roads'}) {
const mapStyle = React.useMemo(() => { const mapStyle = React.useMemo(() => {
if (mode === 'roads') { if (mode === 'roads') {
return mapSource && obsRoads(mapSource) return mapSource && obsRoads(mapSource)
@ -17,14 +46,13 @@ function CustomMapInner({mapSource, config, mode, children}: {mapSource: string,
} }
}, [mapSource, mode]) }, [mapSource, mode])
const [viewport, setViewport] = React.useState({ const [viewportState, setViewportState] = React.useState(EMPTY_VIEWPORT)
longitude: 0, const [viewportUrl, setViewportUrl] = useViewportFromUrl()
latitude: 0,
zoom: 0, const [viewport, setViewport] = viewportFromUrl ? [viewportUrl, setViewportUrl] : [viewportState, setViewportState]
})
React.useEffect(() => { React.useEffect(() => {
if (config?.mapHome) { if (config?.mapHome && viewport.zoom === 0) {
setViewport(config.mapHome) setViewport(config.mapHome)
} }
}, [config]) }, [config])
@ -62,7 +90,7 @@ export default function MapPage() {
return ( return (
<Page fullScreen> <Page fullScreen>
<div className={styles.mapContainer}> <div className={styles.mapContainer}>
<CustomMap mode='roads' /> <CustomMap mode='roads' viewportFromUrl />
</div> </div>
</Page> </Page>
) )