fix: Sửa lỗi bản đồ không full màn hình và không zoom được trên iOS

- Dùng viewportHeight từ JS thay vì CSS dvh để tránh vấn đề iOS Safari
- Thêm MapSizeHandler gọi invalidateSize() để Leaflet tính lại kích thước
- Bật scrollWheelZoom, touchZoom, doubleClickZoom, dragging, inertia
- Đặt maxZoom=20, minZoom=2 rõ ràng
- Loại bỏ max-width/overflow-x trong index.css để không ảnh hưởng trang khác
This commit is contained in:
2026-06-25 10:33:01 +07:00
parent f74587376e
commit b8bf4f88cc
+37 -3
View File
@@ -77,16 +77,42 @@ const MapRefSetter = ({ mapRef }: { mapRef: React.MutableRefObject<L.Map | null>
return null; return null;
}; };
const MapSizeHandler = () => {
const map = useMap();
useEffect(() => {
const timer = setTimeout(() => {
map.invalidateSize();
}, 0);
return () => clearTimeout(timer);
}, [map]);
return null;
};
export const TourNavigationPage: React.FC<TourNavigationPageProps> = ({ tourId, routeData, onBack }) => { export const TourNavigationPage: React.FC<TourNavigationPageProps> = ({ tourId, routeData, onBack }) => {
const [isCompassActive, setIsCompassActive] = useState(false); const [isCompassActive, setIsCompassActive] = useState(false);
const [currentHeading, setCurrentHeading] = useState(0); const [currentHeading, setCurrentHeading] = useState(0);
const [routeGeometry, setRouteGeometry] = useState<[number, number][] | null>(null); const [routeGeometry, setRouteGeometry] = useState<[number, number][] | null>(null);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [viewportHeight, setViewportHeight] = useState(() => {
return Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
});
const mapRef = useRef<L.Map | null>(null); const mapRef = useRef<L.Map | null>(null);
const watchIdRef = useRef<number | null>(null); const watchIdRef = useRef<number | null>(null);
const fetchLockRef = useRef(false); const fetchLockRef = useRef(false);
useEffect(() => {
const handleResize = () => {
setViewportHeight(Math.max(document.documentElement.clientHeight, window.innerHeight || 0));
};
window.addEventListener('resize', handleResize);
window.addEventListener('orientationchange', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
window.removeEventListener('orientationchange', handleResize);
};
}, []);
const originLat = routeData?.origin?.lat; const originLat = routeData?.origin?.lat;
const originLng = routeData?.origin?.lng; const originLng = routeData?.origin?.lng;
const destLat = routeData?.destination?.lat; const destLat = routeData?.destination?.lat;
@@ -200,8 +226,8 @@ export const TourNavigationPage: React.FC<TourNavigationPageProps> = ({ tourId,
: [0, 0]; : [0, 0];
return ( return (
<div className="fixed inset-0 bg-slate-950 flex flex-col overflow-hidden select-none text-white antialiased"> <div className="fixed inset-0 bg-slate-950 flex flex-col overflow-hidden select-none text-white antialiased" style={{ height: '100dvh', height: '-webkit-fill-available' }}>
<div className="w-full bg-[#1e293b]/95 backdrop-blur-md border-b border-slate-800 px-4 py-3.5 flex items-center gap-3 z-50"> <div className="w-full bg-[#1e293b]/95 backdrop-blur-md border-b border-slate-800 px-4 py-3.5 flex items-center gap-3 z-50 shrink-0">
<button <button
onClick={onBack} onClick={onBack}
className="text-slate-300 hover:text-white p-1 rounded-lg hover:bg-slate-800 transition-colors" className="text-slate-300 hover:text-white p-1 rounded-lg hover:bg-slate-800 transition-colors"
@@ -214,15 +240,23 @@ export const TourNavigationPage: React.FC<TourNavigationPageProps> = ({ tourId,
</h2> </h2>
</div> </div>
<div className="flex-1 relative h-[calc(100vh-56px)]"> <div className="flex-1 relative min-h-0" style={{ height: viewportHeight - 56 }}>
<MapContainer <MapContainer
center={center} center={center}
zoom={14} zoom={14}
className="absolute inset-0 h-full w-full" className="absolute inset-0 h-full w-full"
zoomControl={true} zoomControl={true}
attributionControl={false} attributionControl={false}
scrollWheelZoom={true}
doubleClickZoom={true}
touchZoom={true}
dragging={true}
inertia={true}
maxZoom={20}
minZoom={2}
> >
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution="" /> <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution="" />
<MapSizeHandler />
<MapRefSetter mapRef={mapRef} /> <MapRefSetter mapRef={mapRef} />
{routeData.origin && ( {routeData.origin && (
<Marker position={[routeData.origin.lat, routeData.origin.lng]} icon={userIcon}> <Marker position={[routeData.origin.lat, routeData.origin.lng]} icon={userIcon}>