L'PlaceSearchElement
è un elemento HTML che esegue il rendering dei risultati di una ricerca di luoghi in un elenco. Esistono due modi per
configurare l'elemento gmp-place-search
:
- Utilizza la richiesta di ricerca nelle vicinanze per visualizzare i risultati di ricerca utilizzando
PlaceNearbySearchRequestElement
- Utilizza la richiesta di ricerca per testo per visualizzare i risultati di ricerca utilizzando
il
PlaceTextSearchRequestElement
Cerca nelle vicinanze
Seleziona un tipo di luogo dal menu per visualizzare i risultati di ricerca nelle vicinanze per quel tipo di luogo.
L'esempio seguente esegue il rendering dell'elemento Place
Search in risposta a una ricerca nelle vicinanze. Per semplicità, sono elencati solo tre tipi di luoghi:
caffè, ristorante e stazione di ricarica per veicoli elettrici. Quando viene selezionato un risultato, vengono visualizzati un indicatore e
PlaceDetailsCompactElement per il luogo selezionato. Per aggiungere l'elemento
Ricerca luoghi alla mappa, aggiungi un
elemento gmp-place-search
contenente un
elemento gmp-place-nearby-search-request
alla pagina HTML come mostrato nel
seguente snippet:
<div class="list-container"> <div id="map-container"></div> <div class="controls"> <select name="types" class="type-select"> <option value="">Select a place type</option> <option value="cafe">Cafe</option> <option value="restaurant">Restaurant</option> <option value="electric_vehicle_charging_station">EV charging station</option> </select> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-nearby-search-request ></gmp-place-nearby-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div>
Per selezionare gli elementi della pagina per l'interazione vengono utilizzate diverse chiamate querySelector
:
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-nearby-search-request"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request"); const typeSelect = document.querySelector(".type-select");
Quando l'utente seleziona un tipo di luogo dal menu, l'elemento
gmp-place-nearby-search-request
viene aggiornato e l'elemento Ricerca luogo
mostra i risultati (i marcatori vengono aggiunti nella funzione helper addMarkers
):
typeSelect.addEventListener('change', (event) => { event.preventDefault(); searchPlaces(); }); function searchPlaces(){ const bounds = gMap.getBounds(); placeDetailsPopup.map = null; if (typeSelect.value) { placeSearch.style.display = 'block'; placeSearchQuery.maxResultCount = 10; placeSearchQuery.locationRestriction = { center: cent, radius: 1000 }; placeSearchQuery.includedTypes = [typeSelect.value]; placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); } }
Visualizza l'esempio di codice completo
JavaScript
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-nearby-search-request"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request"); const typeSelect = document.querySelector(".type-select"); let markers = {}; let gMap; let placeDetailsPopup; let spherical; let AdvancedMarkerElement; let LatLngBounds; let LatLng; async function init() { console.log("init"); ({ spherical } = await google.maps.importLibrary('geometry')); const {Map} = await google.maps.importLibrary("maps"); await google.maps.importLibrary("places"); ({AdvancedMarkerElement} = await google.maps.importLibrary("marker")); ({LatLngBounds, LatLng} = await google.maps.importLibrary("core")); let mapOptions = { center: {lat: -37.813, lng: 144.963}, zoom: 16, mapTypeControl: false, clickableIcons: false, mapId: 'DEMO_MAP_ID' }; gMap = new Map(mapContainer, mapOptions); placeDetailsPopup = new AdvancedMarkerElement({ map: null, content: placeDetails, zIndex: 100 }); findCurrentLocation(); gMap.addListener('click', (e) => { hidePlaceDetailsPopup(); }); typeSelect.addEventListener('change', (event) => { event.preventDefault(); searchPlaces(); }); placeSearch.addEventListener("gmp-select", ({ place }) => { if (markers[place.id]) { markers[place.id].click(); } }); } function searchPlaces(){ const bounds = gMap.getBounds(); const cent = gMap.getCenter(); const ne = bounds.getNorthEast(); const sw = bounds.getSouthWest(); const diameter = spherical.computeDistanceBetween(ne, sw); const cappedRadius = Math.min((diameter / 2 ), 50000); // Radius cannot be more than 50000. placeDetailsPopup.map = null; for(const markerId in markers){ if (Object.prototype.hasOwnProperty.call(markers, markerId)) { markers[markerId].map = null; } } markers = {}; if (typeSelect.value) { mapContainer.style.height = '75vh'; placeSearch.style.display = 'block'; placeSearchQuery.maxResultCount = 10; placeSearchQuery.locationRestriction = { center: cent, radius: cappedRadius }; placeSearchQuery.includedTypes = [typeSelect.value]; placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); console.log("selection!"); console.log(cappedRadius); } } async function addMarkers(){ const bounds = new LatLngBounds(); placeSearch.style.display = 'block'; if(placeSearch.places.length > 0){ placeSearch.places.forEach((place) => { let marker = new AdvancedMarkerElement({ map: gMap, position: place.location }); marker.metadata = {id: place.id}; markers[place.id] = marker; bounds.extend(place.location); marker.addListener('click',(event) => { placeRequest.place = place; placeDetails.style.display = 'block'; placeDetailsPopup.position = place.location; placeDetailsPopup.map = gMap; gMap.fitBounds(place.viewport, {top: 0, left: 400}); placeDetails.addEventListener('gmp-load',() => { gMap.fitBounds(place.viewport, {top: 0, right: 450}); }, { once: true }); }); gMap.setCenter(bounds.getCenter()); gMap.fitBounds(bounds); }); } } async function findCurrentLocation(){ const { LatLng } = await google.maps.importLibrary("core"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const pos = new LatLng(position.coords.latitude,position.coords.longitude); gMap.panTo(pos); gMap.setZoom(16); }, () => { console.log('The Geolocation service failed.'); gMap.setZoom(16); }, ); } else { console.log("Your browser doesn't support geolocation"); gMap.setZoom(16); } } function hidePlaceDetailsPopup() { if (placeDetailsPopup.map) { placeDetailsPopup.map = null; placeDetails.style.display = 'none'; } } init();
CSS
html, body { height: 100%; margin: 0; } body { display: flex; flex-direction: column; font-family: Arial, Helvetica, sans-serif; } h1 { font-size: large; text-align: center; } #map-container { flex-grow: 1; max-height:600px; box-sizing: border-box; width: 100%; height: 100vh; } .controls { position: absolute; top: 40px; right: 40px; } .list-container { display: flex; position: absolute; max-height: 500px; top: 80px; right: 40px; overflow-y: none; } .type-select { width: 400px; height: 32px; border: 1px solid #000; border-radius: 10px; flex-grow: 1; padding: 0 10px; } gmp-place-search { width: 400px; margin: 0; border-radius: 10px; display: none; border: none; } gmp-place-details-compact { width: 350px; max-height: 800px; margin-right: 20px; display: none; border: none; } gmp-place-details-compact::after { content: ''; position: absolute; bottom: -18px; left: 50%; transform: translateX(-50%); width: 20px; height: 20px; background-color: white; box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.2); z-index: 1; clip-path: polygon(0% 0%, 100% 0%, 50% 100%); transform-origin: center center; } @media (prefers-color-scheme: dark) { /* Style for Dark mode */ gmp-place-details-compact::after { background-color: #131314; } }
HTML
<!DOCTYPE html> <html> <head> <title>Place Search with Compact Place Details Element</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <div id="map-container"></div> <div class="controls"> <select name="types" class="type-select"> <option value="">Select a place type</option> <option value="cafe">Cafe</option> <option value="restaurant">Restaurant</option> <option value="electric_vehicle_charging_station">EV charging station</option> </select> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-nearby-search-request ></gmp-place-nearby-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "YOUR_API_KEY", v: "weekly"}); </script> </body> </html>
Ricerca tramite richiesta di testo
Inserisci un termine di ricerca nel campo di input e fai clic sul pulsante Cerca per visualizzare un elenco di luoghi che corrispondono al termine.
Questo esempio esegue il rendering dell'elemento Ricerca di luoghi in risposta a una ricerca di testo dell'utente. Quando viene selezionato un risultato, vengono visualizzati un indicatore e un
PlaceDetailsCompactElement per il luogo selezionato. Per aggiungere l'elemento
Ricerca luoghi alla mappa, aggiungi un
elemento gmp-place-search
contenente un
elemento gmp-place-search-text-search-request
alla pagina HTML come mostrato nel
seguente snippet:
<div id="map-container"></div> <div class="controls"> <input type="text" class="query-input" /> <button class="search-button">Search</button> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-text-search-request></gmp-place-text-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div>
Per selezionare gli elementi della pagina per l'interazione vengono utilizzate diverse chiamate querySelector
:
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-text-search-request"); const queryInput = document.querySelector(".query-input"); const searchButton = document.querySelector(".search-button"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request");
Quando la funzione di ricerca viene eseguita dopo che l'utente ha inserito una query di ricerca, l'elemento
gmp-place-text-search-request
viene aggiornato e l'elemento Ricerca luoghi
mostra i risultati (i marcatori vengono aggiunti nella funzione helper addMarkers
):
searchButton.addEventListener("click", searchPlaces); queryInput.addEventListener("keydown", (event) => { if (event.key == 'Enter') { event.preventDefault(); searchPlaces(); } }); function searchPlaces(){ if (queryInput.value) { placeSearch.style.display = 'block'; placeSearchQuery.textQuery = queryInput.value; placeSearchQuery.locationBias = gMap.getBounds(); placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); } }
Visualizza l'esempio di codice completo
JavaScript
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-text-search-request"); const queryInput = document.querySelector(".query-input"); const searchButton = document.querySelector(".search-button"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request"); let markers = {}; let previousSearchQuery = ''; let gMap; let placeDetailsPopup; let AdvancedMarkerElement; let LatLngBounds; let LatLng; async function init() { const {Map} = await google.maps.importLibrary("maps"); await google.maps.importLibrary("places"); ({AdvancedMarkerElement} = await google.maps.importLibrary("marker")); ({LatLngBounds, LatLng} = await google.maps.importLibrary("core")); let mapOptions = { center: {lat: 37.422, lng: -122.085}, zoom: 2, mapTypeControl: false, clickableIcons: false, mapId: 'DEMO_MAP_ID' }; gMap = new Map(mapContainer, mapOptions); placeDetailsPopup = new AdvancedMarkerElement({ map: null, content: placeDetails, zIndex: 100 }); findCurrentLocation(); gMap.addListener('click', (e) => { hidePlaceDetailsPopup(); }); searchButton.addEventListener("click", searchPlaces); queryInput.addEventListener("keydown", (event) => { if (event.key == 'Enter') { event.preventDefault(); searchPlaces(); } }); placeSearch.addEventListener("gmp-select", ({ place }) => { if (markers[place.id]) { markers[place.id].click(); } }); } function searchPlaces(){ if (queryInput.value.trim() === previousSearchQuery) { return; } previousSearchQuery = queryInput.value.trim(); placeDetailsPopup.map = null; for(const markerId in markers){ if (Object.prototype.hasOwnProperty.call(markers, markerId)) { markers[markerId].map = null; } } markers = {}; if (queryInput.value) { // mapContainer.style.height = '75vh'; placeSearch.style.display = 'block'; placeSearchQuery.textQuery = queryInput.value; placeSearchQuery.locationBias = gMap.getBounds(); placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); } } async function addMarkers(){ const bounds = new LatLngBounds(); if(placeSearch.places.length > 0){ placeSearch.places.forEach((place) => { let marker = new AdvancedMarkerElement({ map: gMap, position: place.location }); marker.metadata = {id: place.id}; markers[place.id] = marker; bounds.extend(place.location); marker.addListener('click',(event) => { placeRequest.place = place; placeDetails.style.display = 'block'; placeDetailsPopup.position = place.location; placeDetailsPopup.map = gMap; gMap.fitBounds(place.viewport, {top: 200, right: 450}); }); gMap.setCenter(bounds.getCenter()); gMap.fitBounds(bounds); }); } } async function findCurrentLocation(){ const { LatLng } = await google.maps.importLibrary("core"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const pos = new LatLng(position.coords.latitude,position.coords.longitude); gMap.panTo(pos); gMap.setZoom(16); }, () => { console.log('The Geolocation service failed.'); gMap.setZoom(16); }, ); } else { console.log("Your browser doesn't support geolocation"); gMap.setZoom(16); } } function hidePlaceDetailsPopup() { if (placeDetailsPopup.map) { placeDetailsPopup.map = null; placeDetails.style.display = 'none'; } } init();
CSS
html, body { height: 100%; margin: 0; } body { display: flex; flex-direction: column; font-family: Arial, Helvetica, sans-serif; } h1 { font-size: large; text-align: center; } #map-container { flex-grow: 1; max-height:600px; box-sizing: border-box; width: 100%; height: 100vh; } .controls { border-radius: 5px; position: absolute; top: 40px; right: 40px; } .search-button { background-color: #4b4b4b; color: #fff; border: 1px solid #000; border-radius: 10px; width: 80px; height: 40px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35); } .query-input { border: 1px solid #ccc; border-radius: 10px; width: 315px; height: 40px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35); } .list-container { display: flex; position: absolute; max-height: 500px; top: 100px; right: 40px; overflow-y: none; } gmp-place-search { width: 400px; margin: 0; border-radius: 10px; display: none; border: none; } gmp-place-details-compact { width: 350px; max-height: 800px; display: none; border: none; transform: translateY(calc(-40%)); } gmp-place-details-compact::after { content: ''; position: absolute; bottom: -18px; left: 50%; transform: translateX(-50%); width: 20px; height: 20px; background-color: white; box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.2); z-index: 1; clip-path: polygon(0% 0%, 100% 0%, 50% 100%); transform-origin: center center; } @media (prefers-color-scheme: dark) { /* Style for Dark mode */ gmp-place-details-compact::after { background-color: #131314; } }
HTML
<!DOCTYPE html> <html> <head> <title>Place Search with a Details Popup</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <div id="map-container"></div> <div class="controls"> <input type="text" class="query-input" /> <button class="search-button">Search</button> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-text-search-request></gmp-place-text-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "YOUR_API_KEY", v: "weekly"}); </script> </body> </html>