feat: add map reset functionality and improve incident popup handling

This commit is contained in:
vergiLgood1 2025-05-05 03:42:32 +07:00
parent 6327d7b886
commit c282d958a5
3 changed files with 175 additions and 115 deletions

View File

@ -21,6 +21,7 @@ import { CrimeTimelapse } from "./controls/bottom/crime-timelapse"
import { ITooltips } from "./controls/top/tooltips"
import CrimeSidebar from "./controls/left/sidebar/map-sidebar"
import Tooltips from "./controls/top/tooltips"
import { BASE_BEARING, BASE_PITCH, BASE_ZOOM } from "@/app/_utils/const/map"
// Updated CrimeIncident type to match the structure in crime_incidents
interface ICrimeIncident {
@ -225,6 +226,57 @@ export default function CrimeMap() {
};
}, []);
// Add event listener for map reset
useEffect(() => {
const handleMapReset = (e: CustomEvent) => {
const { duration } = e.detail || { duration: 1500 };
// Find the map instance
const mapInstance = mapContainerRef.current?.querySelector('.mapboxgl-map');
if (!mapInstance) {
console.error("Map instance not found");
return;
}
// Create and dispatch the reset event that MapView will listen for
const mapboxEvent = new CustomEvent('mapbox_fly', {
detail: {
duration: duration,
resetCamera: true
},
bubbles: true
});
mapInstance.dispatchEvent(mapboxEvent);
};
// Add event listener
document.addEventListener('mapbox_reset', handleMapReset as EventListener);
return () => {
document.removeEventListener('mapbox_reset', handleMapReset as EventListener);
};
}, []);
// Update the popup close handler to reset the map view
const handlePopupClose = () => {
setSelectedIncident(null);
// Dispatch map reset event to reset zoom, pitch, and bearing
const mapInstance = mapContainerRef.current?.querySelector('.mapboxgl-map');
if (mapInstance) {
const resetEvent = new CustomEvent('mapbox_reset', {
detail: {
duration: 1500,
},
bubbles: true
});
mapInstance.dispatchEvent(resetEvent);
}
}
// Handle year-month timeline change
const handleTimelineChange = useCallback((year: number, month: number, progress: number) => {
setSelectedYear(year)
@ -262,11 +314,6 @@ export default function CrimeMap() {
return title
}
// Toggle sidebar function
const toggleSidebar = useCallback(() => {
setSidebarCollapsed(!sidebarCollapsed)
}, [sidebarCollapsed])
// Handle control changes from the top controls component
const handleControlChange = (controlId: ITooltips) => {
setActiveControl(controlId)
@ -327,7 +374,7 @@ export default function CrimeMap() {
<CrimePopup
longitude={selectedIncident.longitude}
latitude={selectedIncident.latitude}
onClose={() => setSelectedIncident(null)}
onClose={handlePopupClose}
incident={selectedIncident}
/>

View File

@ -88,8 +88,20 @@ export default function MapView({
const handleMapFly = (e: CustomEvent) => {
if (!e.detail || !mapRef.current) return;
const { center, zoom, bearing, pitch, duration } = e.detail;
const { center, zoom, bearing, pitch, duration, resetCamera } = e.detail;
if (resetCamera) {
// Reset to default view
mapRef.current.flyTo({
center: [BASE_LONGITUDE, BASE_LATITUDE],
zoom: BASE_ZOOM,
bearing: BASE_BEARING,
pitch: BASE_PITCH,
duration,
essential: true
});
} else {
// Fly to specific location
mapRef.current.flyTo({
center,
zoom,
@ -98,6 +110,7 @@ export default function MapView({
duration,
essential: true
});
}
};
mapElement.addEventListener('mapbox_fly', handleMapFly as EventListener);

View File

@ -75,7 +75,7 @@ export default function IncidentPopup({ longitude, latitude, onClose, incident }
<Popup
longitude={longitude}
latitude={latitude}
closeButton={false} // Hide default close button
closeButton={false}
closeOnClick={false}
onClose={onClose}
anchor="top"