- Creazione "AbitareGliIblei"

- Mappa Interattiva con i markers
This commit is contained in:
Surya Paolo
2024-07-31 15:02:30 +02:00
parent 3ab18b591f
commit 822585cf33
252 changed files with 3600294 additions and 4300 deletions

View File

@@ -0,0 +1,3 @@
.map-container {
height: 400px;
}

View File

@@ -0,0 +1,170 @@
import { tools } from '@store/Modules/tools'
import { useQuasar } from 'quasar'
import { defineComponent, onMounted, ref, watch, computed } from 'vue'
import 'leaflet/dist/leaflet.css'
import * as L from 'leaflet'
import 'leaflet.markercluster/dist/MarkerCluster.css'
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
import 'leaflet.markercluster'
import { useUserStore } from '@src/store/UserStore'
// Importa le immagini dei marker
import icon from 'leaflet/dist/images/marker-icon.png'
import iconShadow from 'leaflet/dist/images/marker-shadow.png'
export default defineComponent({
name: 'CMapGetCoordinates',
setup(props, { emit }) {
const $q = useQuasar()
const userStore = useUserStore()
const iconWidth = ref(25)
const iconHeight = ref(41)
const map = ref<L.Map | null>(null)
const marker = ref<L.Marker | null>(null)
const address = ref('')
const suggestions = ref([]);
const coordinates = ref(<[number, number]>[0, 0])
const isMapDialogOpen = ref(false)
const zoomLevel = ref(17)
const myheight = computed(() => {
return $q.screen.height - 150
})
const initMap = () => {
// Configura l'icona di default
const DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow,
iconSize: [iconWidth.value, iconHeight.value],
iconAnchor: [iconWidth.value / 2, iconHeight.value],
popupAnchor: [1, -iconHeight.value],
shadowSize: [iconHeight.value, iconHeight.value]
})
L.Marker.prototype.options.icon = DefaultIcon
map.value = L.map('map',
{
zoomControl: true, zoom: zoomLevel.value, zoomAnimation: true,
fadeAnimation: true, markerZoomAnimation: true,
center: [42.71, 12.934],
}
)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map.value)
const closeButton = L.control({ position: 'topright' });
closeButton.onAdd = function () {
const button = L.DomUtil.create('button', 'leaflet-control-button');
button.innerHTML = 'Chiudi'; // Testo del pulsante
button.style.backgroundColor = 'red';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '5px';
button.style.padding = '10px';
button.style.cursor = 'pointer';
button.onclick = () => {
isMapDialogOpen.value = false; // Chiudi il dialog della mappa
};
return button;
};
closeButton.addTo(map.value);
}
const updateMarker = (lat: number, lng: number) => {
console.log('aggiorna marker', lat, lng)
if (marker.value) {
marker.value.setLatLng([lat, lng])
} else {
marker.value = L.marker([lat, lng], { draggable: true }).addTo(map.value!)
marker.value.on('dragend', (event: L.LeafletEvent) => {
const position = (event.target as L.Marker).getLatLng()
coordinates.value = [
parseFloat(position.lng.toFixed(6)),
parseFloat(position.lat.toFixed(6)),
]
emit('update:coordinates', coordinates.value)
})
}
map.value?.setView([lat, lng], 17)
}
const searchAddress = async () => {
try {
const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address.value)}`)
const data = await response.json()
if (data && data.length > 0) {
coordinates.value = [
parseFloat(data[0].lon),
parseFloat(data[0].lat)
]
emit('update:coordinates', coordinates.value)
isMapDialogOpen.value = true
}
} catch (error) {
console.error('Error searching address:', error)
}
}
const getAddressSuggestions = async (val: string, update: Function) => {
try {
if (val.length === 0) {
suggestions.value = [];
update();
return;
}
const response = await fetch(
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(val)}`
);
const data = await response.json();
suggestions.value = data.map((item: any) => ({
label: item.display_name,
value: item.display_name,
lat: item.lat,
lon: item.lon
}));
update();
} catch (error) {
console.error('Error fetching address suggestions:', error);
}
};
watch(address, (newAddress) => {
const match: any = suggestions.value.find((suggestion: any) => suggestion.value === newAddress.value);
if (match && match.lat) {
coordinates.value = [
parseFloat(parseFloat(match.lon).toFixed(6)),
parseFloat(parseFloat(match.lat).toFixed(6))
]
};
updateMarker(coordinates.value[1], coordinates.value[0]);
});
onMounted(() => {
initMap()
})
return {
address,
coordinates,
searchAddress,
myheight,
isMapDialogOpen,
suggestions,
getAddressSuggestions,
}
}
})

View File

@@ -0,0 +1,57 @@
<template>
<div class="q-pa-sm">
<div class="q-gutter-sm">
<div class="row q-col-gutter-sm q-mb-sm items-center no-wrap">
<div class="col-grow">
<q-select
v-model="address"
label="Indirizzo"
use-input
input-class="col-auto"
input-debounce="300"
:options="suggestions"
@filter="getAddressSuggestions"
filled
dense
hide-dropdown-icon
clearable
/>
</div>
<div class="col-3">
<q-btn @click="searchAddress" label="Cerca" color="primary" />
</div>
</div>
<div class="row q-col-gutter-sm">
<q-col cols="6">
<q-input
v-model="coordinates.lat" label="Latitudine:"
filled dense />
</q-col>
<q-col cols="6">
<q-input
v-model="coordinates.lng"
label="Longitudine:"
filled
dense
/>
</q-col>
</div>
</div>
<div
id="map"
:style="`height:${myheight}px; width:99%`"
>
<p v-if="coordinates && coordinates.lat">
Coordinate: {{ coordinates.lat.toFixed(6) }},
{{ coordinates.lng.toFixed(6) }}
</p>
</div>
</div>
</template>
<script lang="ts" src="./CMapGetCoordinates.ts">
</script>
<style lang="scss" scoped>
@import './CMapGetCoordinates.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CMapGetCoordinates} from './CMapGetCoordinates.vue'