diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a2e2459..e1039b1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,6 +14,7 @@ "leaflet": "^1.9.4", "leaflet-draw": "^1.0.2", "leaflet-easybutton": "^2.4.0", + "leaflet-groupedlayercontrol": "^0.6.1", "leaflet-iconmaterial": "^1.1.0", "leaflet.markercluster": "^1.5.3", "papaparse": "^5.4.1", @@ -5477,6 +5478,15 @@ "leaflet": "^1.0.1" } }, + "node_modules/leaflet-groupedlayercontrol": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/leaflet-groupedlayercontrol/-/leaflet-groupedlayercontrol-0.6.1.tgz", + "integrity": "sha512-xkGeH6ygcryFQI0FUWn6Bz93zlwrOSpeXgJQ3jLRoUQJ5h/Qgrz+GqR9nhBFfikjUKtC1sCKL3eDR9wNTWhLlA==", + "license": "MIT", + "dependencies": { + "leaflet": "^1.0.1" + } + }, "node_modules/leaflet-iconmaterial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/leaflet-iconmaterial/-/leaflet-iconmaterial-1.1.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index f4dc170..fb995f6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "leaflet": "^1.9.4", "leaflet-draw": "^1.0.2", "leaflet-easybutton": "^2.4.0", + "leaflet-groupedlayercontrol": "^0.6.1", "leaflet-iconmaterial": "^1.1.0", "leaflet.markercluster": "^1.5.3", "papaparse": "^5.4.1", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 893f491..f50823f 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -44,13 +44,17 @@ const alertStore = useAlertStore() let showMobileNavigation = ref(false) const paths = [ { - attrs: { to: '/' }, - label: 'Map' + attrs: { to: '/hydrologic_processes' }, + label: 'Hydrologic Processes' }, // { // attrs: { to: "/api" }, // label: "API", // }, + { + attrs: { to: '/perceptual_models' }, + label: 'Perceptual Models' + }, { attrs: { to: '/about' }, label: 'About' diff --git a/frontend/src/components/TheLeafletMap.vue b/frontend/src/components/TheLeafletMap.vue index 1a94353..0c17027 100644 --- a/frontend/src/components/TheLeafletMap.vue +++ b/frontend/src/components/TheLeafletMap.vue @@ -11,7 +11,6 @@ import L from 'leaflet' import 'leaflet-draw' import 'leaflet.markercluster' -import { storeToRefs } from 'pinia' import * as esriLeaflet from 'esri-leaflet' import { onMounted, onUpdated } from 'vue' import { useMapStore } from '@/stores/map' @@ -21,24 +20,13 @@ import 'leaflet-draw/dist/leaflet.draw.css' import 'leaflet.markercluster/dist/MarkerCluster.css' import 'leaflet.markercluster/dist/MarkerCluster.Default.css' -const emit = defineEmits(['onFilter']) - const mapStore = useMapStore() -const { - mapLoaded, - userTouchedFilter, - currentFilteredData, - selectedSpatialZones, - selectedTemporalZones, - selectedProcesses, - searchTerm -} = storeToRefs(mapStore) onUpdated(() => { mapStore.leaflet.invalidateSize() }) -onMounted(async () => { +onMounted(() => { mapStore.leaflet = L.map('mapContainer', { minZoom: 2 }).setView([0, 11], 2) mapStore.layerGroup = new L.LayerGroup() mapStore.layerGroup.addTo(mapStore.leaflet) @@ -77,198 +65,8 @@ onMounted(async () => { Esri_WorldImagery.addTo(mapStore.leaflet) Esri_Hydro_Reference_Overlay.addTo(mapStore.leaflet) - await mapStore.fetchPerceptualModelsGeojson() - const bounds = L.latLngBounds(mapStore.allAvailableCoordinates) - mapStore.leaflet.setMaxBounds(bounds) - - const mixed = { - 'Perceptual Models': mapStore.layerGroup, - 'Esri Hydro Reference Overlay': Esri_Hydro_Reference_Overlay - } - L.control.layers(baselayers, mixed).addTo(mapStore.leaflet) - - const drawnItems = new L.FeatureGroup() - mapStore.drawnItems = drawnItems - mapStore.leaflet.addLayer(drawnItems) - drawnItems.setZIndex(1000) - - let currentRectangle = null - - L.Control.RectangleToggle = L.Control.extend({ - options: { position: 'topleft' }, - onAdd: function () { - const container = L.DomUtil.create( - 'div', - 'leaflet-bar leaflet-control leaflet-control-custom draw-toggle-btn' - ) - updateDrawButton(container) - let drawer = null - L.DomEvent.on(container, 'click', () => { - if (currentRectangle || drawer) { - drawnItems.clearLayers() - currentRectangle = null - mapStore.filterFeatures( - (feature) => { - if (feature.geometry.type === 'Point') { - const [lng, lat] = feature.geometry.coordinates - return currentRectangle.getBounds().contains([lat, lng]) - } - return false - }, - 'remove', - 'rectangle' - ) - userTouchedFilter.value = false - emit('onFilter', { - selectedSpatialZones, - selectedTemporalZones, - selectedProcesses, - searchTerm, - filteredFeatures: currentFilteredData.value - }) - updateDrawButton(container) - } else { - const drawer = new L.Draw.Rectangle(mapStore.leaflet, { - shapeOptions: { - color: '#3388ff', - weight: 2, - opacity: 0.8, - fillOpacity: 0.3 - }, - showArea: false - }) - drawer.enable() - currentRectangle = {} - updateDrawButton(container) - - const drawHandler = (e) => { - mapStore.leaflet.off(L.Draw.Event.CREATED, drawHandler) - drawnItems.clearLayers() - currentRectangle = e.layer - currentRectangle.feature = { - type: 'Feature', - geometry: { - type: 'Polygon', - coordinates: [ - currentRectangle.getLatLngs()[0].map((latLng) => [latLng.lng, latLng.lat]) - ] - }, - properties: {} - } - drawnItems.addLayer(currentRectangle) - mapStore.leaflet.fitBounds(currentRectangle.getBounds()) - - mapStore.filterFeatures( - (feature) => { - if (feature.geometry.type === 'Point') { - const [lng, lat] = feature.geometry.coordinates - return currentRectangle.getBounds().contains([lat, lng]) - } - return false - }, - 'add', - 'rectangle' - ) - - userTouchedFilter.value = true - emit('onFilter', { - selectedSpatialZones, - selectedTemporalZones, - selectedProcesses, - searchTerm, - filteredFeatures: currentFilteredData.value - }) - - updateDrawButton(container) - } - - mapStore.leaflet.on(L.Draw.Event.CREATED, drawHandler) - mapStore.leaflet.once('draw:drawstop', () => { - // If no rectangle was drawn, reset the toggle state - if (!drawnItems.getLayers().length) { - currentRectangle = null - updateDrawButton(container) - mapStore.leaflet.off(L.Draw.Event.CREATED, drawHandler) - } - }) - } - }) - - return container - } - }) - mapStore.leaflet.addControl(new L.Control.RectangleToggle()) - - function updateDrawButton(container) { - if (currentRectangle) { - container.innerHTML = 'close' - container.style.background = 'white' - container.title = 'Clear box' - } else { - container.style.backgroundImage = "url('/DrawIcon.ico')" - container.innerHTML = '' - container.title = 'Draw a box' - } - container.style.backgroundRepeat = 'no-repeat' - container.style.backgroundSize = '60% 60%' - container.style.backgroundPosition = 'center' - container.style.borderRadius = '4px' - container.style.width = '34px' - container.style.height = '34px' - container.style.cursor = 'pointer' - container.style.display = 'flex' - container.style.alignItems = 'center' - container.style.justifyContent = 'center' - } - L.drawLocal.draw.handlers.rectangle.tooltip.start = 'Click and drag to draw a box' - L.Control.ClearFilters = L.Control.extend({ - options: { position: 'topleft' }, - onAdd: function () { - const container = L.DomUtil.create( - 'div', - 'leaflet-bar leaflet-control leaflet-control-custom' - ) - container.title = 'Reset Filters' - - container.style.backgroundImage = "url('/ClearFilter.ico')" - container.style.backgroundRepeat = 'no-repeat' - container.style.backgroundSize = '60% 60%' - container.style.backgroundColor = 'white' - container.style.backgroundPosition = 'center' - container.style.borderRadius = '4px' - container.style.width = '34px' - container.style.height = '34px' - container.style.cursor = 'pointer' - container.style.display = 'flex' - container.style.alignItems = 'center' - container.style.justifyContent = 'center' - - L.DomEvent.on(container, 'click', () => { - mapStore.clearAllFilters() - emit('onFilter', { - selectedSpatialZones, - selectedTemporalZones, - selectedProcesses, - searchTerm, - filteredFeatures: currentFilteredData.value - }) - }) - - return container - } - }) - mapStore.leaflet.addControl(new L.Control.ClearFilters()) - - mapStore.leaflet.on('click', function (e) { - mapClick(e) - }) - - mapLoaded.value = true + L.control.layers(baselayers).addTo(mapStore.leaflet) }) - -async function mapClick() { - return -}