From 57f253c10b6c25e34797a1c0d1909e0063f80435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Weckm=C3=BCller?= <47481567+do-me@users.noreply.github.com> Date: Fri, 27 Dec 2024 17:34:18 +0100 Subject: [PATCH] Add files via upload --- index.html | 22 ++++++++ main.js | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++ styles.css | 98 ++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+) create mode 100644 index.html create mode 100644 main.js create mode 100644 styles.css diff --git a/index.html b/index.html new file mode 100644 index 0000000..962d73c --- /dev/null +++ b/index.html @@ -0,0 +1,22 @@ + + + + + MapLibre GL JS with Geocoder + + + + + + +
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..7abe1d4 --- /dev/null +++ b/main.js @@ -0,0 +1,153 @@ +var map = new maplibregl.Map({ + container: 'map', + style: 'https://sgx.geodatenzentrum.de/gdz_basemapworld_vektor/styles/bm_web_wld_col.json', + center: [10, 51], + zoom: 6, +}); + +const addressInput = document.getElementById('addressInput'); +const searchResults = document.getElementById('searchResults'); +let marker = null; +let resultsVisible = false; + + +async function geocodeAddress(address) { +const photonUrl = `https://photon.komoot.io/api/?q=${encodeURIComponent(address)}`; + try { + const response = await fetch(photonUrl); + const data = await response.json(); + + if (data && data.features && data.features.length > 0) { + const result = data.features[0]; + const coords = result.geometry.coordinates; + updateMapAndMarker(coords); + clearSearchResults(); + + } else { + alert('No results found for this address.'); + } + } catch (error) { + console.error('Error during geocoding', error); + alert('Error during geocoding.'); + } +} + +function updateMapAndMarker(coords) { +map.flyTo({ + center: coords, + zoom: 15, +}); + +if (marker) { + marker.remove(); +} + +marker = new maplibregl.Marker() + .setLngLat(coords) + .addTo(map); +} + +async function fetchSuggestions(address) { +if (!address) { + clearSearchResults(); + return; +} + +const photonUrl = `https://photon.komoot.io/api/?q=${encodeURIComponent(address)}&limit=5`; + try { + const response = await fetch(photonUrl); + const data = await response.json(); + displaySuggestions(data.features); + } catch (error) { + console.error('Error fetching suggestions', error); + } +} + +function displaySuggestions(results) { +clearSearchResults(); + +if (!results || results.length === 0) { + resultsVisible = false; + searchResults.style.display = 'none'; + return; +} + +results.forEach(result => { + const props = result.properties; + let addressParts = []; + + if (props.name) { + addressParts.push(props.name); + } + if (props.street) { + addressParts.push(props.street); + } + if (props.housenumber) { + addressParts.push(props.housenumber) + } + + if(props.postcode && props.city) { + addressParts.push(props.postcode + ' ' + props.city ) + } + + const addressString = addressParts.join(', '); + + const listItem = document.createElement('li'); + listItem.textContent = addressString; + + listItem.addEventListener('click', () => { + const coords = result.geometry.coordinates; + addressInput.value = listItem.textContent; + updateMapAndMarker(coords); + clearSearchResults(); + }); + + searchResults.appendChild(listItem); +}); + resultsVisible = true; + searchResults.style.display = 'block'; +} + +function clearSearchResults() { +searchResults.innerHTML = ''; +searchResults.style.display = 'none'; +resultsVisible = false; +} + + +addressInput.addEventListener('keydown', (event) => { + if (event.key === 'Enter') { + event.preventDefault(); // Prevent form submission + if (searchResults.children.length > 0 ) { + const firstResult = searchResults.children[0]; + firstResult.click(); + } else { + const address = addressInput.value; + if (address) { + geocodeAddress(address); + } else { + alert('Please enter an address.'); + } + } + } +}); + +addressInput.addEventListener('input', () => { + const address = addressInput.value; + fetchSuggestions(address); +}); + + +addressInput.addEventListener('focus', () => { +if (resultsVisible === false && addressInput.value) { + fetchSuggestions(addressInput.value) +} else if (resultsVisible === false) { + clearSearchResults() +} +}); + + +// Event listener to close search results on map click +map.on('click', () => { + clearSearchResults(); +}); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..74377f5 --- /dev/null +++ b/styles.css @@ -0,0 +1,98 @@ +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; /* Improve text rendering on webkit browsers */ + -moz-osx-font-smoothing: grayscale; /* Improve text rendering on firefox */ + background-color: #f8f8f8; /* Light background color */ +} + +#map { + position: absolute; + top: 0; + bottom: 0; + width: 100%; + transition: filter 0.3s ease; /*Smooth transition for map interactions*/ +} + +#geocoder { + position: absolute; + top: 20px; /* Increased top padding to avoid clutter*/ + left: 50%; /* Center on page*/ + transform: translateX(-50%); /* Center on page*/ + z-index: 1; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */ +} + + +#geocoder input { + padding: 10px 14px; /* Padding for comfortable spacing*/ + border: 1px solid #ddd; /* Lighter border for subtle look */ + border-radius: 8px; + width: 450px; /* Reduced width (75% of 600px) */ + box-sizing: border-box; + font-size: 1rem; + color: #333; /* Darker text for better readability */ + transition: border-color 0.3s ease, box-shadow 0.3s ease; /* Smooth transition for input focus */ + outline: none; /* Removing the default outline*/ +} + +#geocoder input:focus { + border-color: #aaa; /* Darker border on focus */ + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); /* More noticeable shadow */ +} + +#searchResults { + position: absolute; + top: calc(100% + 5px); + left: 0; /* Align with the left edge of the input field */ + background-color: white; + border: 1px solid #ddd; /* Lighter border */ + list-style: none; + padding: 0; + margin: 0; + max-height: 250px; /* Slightly more space for results */ + overflow-y: auto; + z-index: 2; + width: 450px; /* Reduced width (75% of 600px) */ + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + border-radius: 8px; + display: none; + box-sizing: border-box; /* Include padding/border in width calculation */ +} + +#searchResults li { + padding: 10px 14px; /* Padding for list items*/ + border-bottom: 1px solid #eee; + cursor: pointer; + color: #333; + transition: background-color 0.2s ease; +} + + +#searchResults li:last-child { + border-bottom: none; +} + +#searchResults li:hover { + background-color: #f0f0f0; /* Light grey on hover */ +} + +/* Custom Scrollbar Styling */ +#searchResults::-webkit-scrollbar { + width: 8px; /* Width of the scrollbar */ +} + +#searchResults::-webkit-scrollbar-track { + background: #f1f1f1; /* Color of the track */ + border-radius: 4px; /* Rounded track */ +} + +#searchResults::-webkit-scrollbar-thumb { + background: #c1c1c1; /* Color of the thumb */ + border-radius: 4px; /* Rounded thumb */ +} + +#searchResults::-webkit-scrollbar-thumb:hover { + background: #a8a8a8; /* Darker color on hover */ +} \ No newline at end of file