diff --git a/frontend/src/pages/TourNavigationPage.tsx b/frontend/src/pages/TourNavigationPage.tsx index 741acb3..2333296 100644 --- a/frontend/src/pages/TourNavigationPage.tsx +++ b/frontend/src/pages/TourNavigationPage.tsx @@ -16,14 +16,14 @@ interface TourNavigationPageProps { onBack: () => void; } -const FitBounds = ({ coords, canFitRef, compassActive }: { coords: [number, number][], canFitRef: React.MutableRefObject, compassActive: boolean }) => { +const FitBounds = ({ coords, canFitRef }: { coords: [number, number][], canFitRef: React.MutableRefObject }) => { const map = useMap(); useEffect(() => { - if (coords.length > 0 && canFitRef.current && !compassActive) { + if (coords.length > 0 && canFitRef.current) { canFitRef.current = false; map.fitBounds(coords, { padding: [60, 60], maxZoom: 15 }); } - }, [map, coords, canFitRef, compassActive]); + }, [map, coords, canFitRef]); return null; }; @@ -70,30 +70,66 @@ const CompassInteractionDetector = ({ return null; }; -const MapRefSetter = ({ mapRef, userInteractedRef }: { mapRef: React.MutableRefObject, userInteractedRef: React.MutableRefObject }) => { +const MapRefSetter = ({ mapRef }: { mapRef: React.MutableRefObject }) => { const map = useMap(); useEffect(() => { mapRef.current = map; - const onZoomEnd = () => { userInteractedRef.current = true; }; - const onMoveEnd = () => { userInteractedRef.current = true; }; + }, [map, mapRef]); + return null; +}; + +const MapInteractionWatcher = () => { + const map = useMap(); + useEffect(() => { + const onZoomEnd = () => { + map._userZoomLevel = map.getZoom(); + }; + const onMoveEnd = () => { + map._userCenter = map.getCenter(); + }; map.on('zoomend', onZoomEnd); map.on('moveend', onMoveEnd); return () => { map.off('zoomend', onZoomEnd); map.off('moveend', onMoveEnd); }; - }, [map, mapRef, userInteractedRef]); + }, [map]); return null; }; const MapSizeHandler = ({ mapRef }: { mapRef: React.MutableRefObject }) => { const map = useMap(); + const prevSizeRef = useRef<{ width: number; height: number } | null>(null); + useEffect(() => { - const timer = setTimeout(() => { - mapRef.current?.invalidateSize(); - }, 100); - return () => clearTimeout(timer); + const container = map.getContainer(); + if (!container) return; + + prevSizeRef.current = { width: container.clientWidth, height: container.clientHeight }; + + const observer = new ResizeObserver(() => { + const newWidth = container.clientWidth; + const newHeight = container.clientHeight; + const prev = prevSizeRef.current; + + if ((prev && (Math.abs(newWidth - prev.width) > 2 || Math.abs(newHeight - prev.height) > 2)) || newWidth === 0 || newHeight === 0) { + prevSizeRef.current = { width: newWidth, height: newHeight }; + const prevZoom = map.getZoom(); + const prevCenter = map.getCenter(); + const userZoom = (map as any)._userZoomLevel as number | undefined; + + map.invalidateSize({ animate: false }); + + if (userZoom !== undefined && Math.abs(map.getZoom() - userZoom) > 0.01) { + map.setZoom(userZoom, { animate: false }); + } + } + }); + + observer.observe(container); + return () => observer.disconnect(); }, [map, mapRef]); + return null; }; @@ -102,12 +138,11 @@ export const TourNavigationPage: React.FC = ({ tourId, const [currentHeading, setCurrentHeading] = useState(0); const [routeGeometry, setRouteGeometry] = useState<[number, number][] | null>(null); const [error, setError] = useState(null); - const userInteractedRef = useRef(false); - const canFitRef = useRef(true); const mapRef = useRef(null); const watchIdRef = useRef(null); const fetchLockRef = useRef(false); + const canFitRef = useRef(true); const originLat = routeData?.origin?.lat; const originLng = routeData?.origin?.lng; @@ -252,26 +287,13 @@ export const TourNavigationPage: React.FC = ({ tourId, minZoom={2} > - - - - {routeData.origin && ( - - -
Bạn đang ở đây
-
-
- )} - {routeData.destination && ( - - -
{routeData.destination.name}
-
-
- )} + + + {routeGeometry && ( )} +