From 933e958d46257890b5c97f375bab797b4a3131cc Mon Sep 17 00:00:00 2001 From: easbar Date: Thu, 20 May 2021 07:08:34 +0200 Subject: [PATCH] Better solution --- src/map/Map.tsx | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/map/Map.tsx b/src/map/Map.tsx index 4828a99f..65de43e1 100644 --- a/src/map/Map.tsx +++ b/src/map/Map.tsx @@ -1,7 +1,7 @@ import { QueryPoint } from '@/stores/QueryStore' import React, { useEffect, useRef, useState } from 'react' import styles from '@/map/Map.module.css' -import Mapbox from '@/map/Mapbox' +import Mapbox, { ViewPort } from '@/map/Mapbox' import Dispatcher from '@/stores/Dispatcher' import { MapIsLoaded } from '@/actions/Actions' import { Bbox, Path } from '@/api/graphhopper' @@ -18,39 +18,39 @@ type MapProps = { export default function({ selectedPath, paths, queryPoints, bbox, mapStyle }: MapProps) { const mapContainerRef: React.RefObject = useRef(null) const [map, setMap] = useState(null) - // we need to keep track of the latest bbox so it is available in the onMapReady callback by the time the Mapbox - // instance is loaded - const prevBbox = useRef() - useEffect(() => { - prevBbox.current = bbox - }, [bbox]) + const prevViewPort = useRef(null) + prevViewPort.current = null useEffect(() => { - // as long as we re-create the Mapbox instance when changing the mapStyle we need to make sure the viewport - // state is preserved - const prevViewPort = map?.getViewPort() - if (map) map.remove() + if (map) { + map.remove() + // save the current view port so we can set it after re-creating the Mapbox instance when we change mapStyle + prevViewPort.current = map.getViewPort() + } const mapWrapper = new Mapbox( mapContainerRef.current!, mapStyle, () => { setMap(mapWrapper) - if (!prevViewPort) - mapWrapper.fitBounds(prevBbox.current!) Dispatcher.dispatch(new MapIsLoaded()) } ) - if (prevViewPort) - mapWrapper.setViewPort(prevViewPort) + if (prevViewPort.current) + mapWrapper.setViewPort(prevViewPort.current) return () => map?.remove() - }, [mapStyle, prevBbox]) + }, [mapStyle]) useEffect(() => map?.drawPaths(paths, selectedPath), [paths, selectedPath, map]) useEffect(() => map?.showPathDetails(selectedPath), [selectedPath, map]) useEffect(() => map?.drawMarkers(queryPoints), [queryPoints, map]) - // no dependency on map here, because in case changed the viewport manually we do not want to go back to the bbox - // after a style change onMapReady - useEffect(() => map?.fitBounds(bbox), [bbox]) + useEffect(() => { + // previous view port takes precedence if it was set. for example when we just changed the mapStyle we do + // not want to go back to the bbox + if (prevViewPort.current) + map?.setViewPort(prevViewPort.current) + else + map?.fitBounds(bbox) + }, [bbox, map, prevViewPort]) return
}