Elemento Place Search

PlaceSearchElement è un elemento HTML che visualizza i risultati di una Place Search in un elenco. Esistono due modi per configurare l'elemento gmp-place-search:

Richiesta di ricerca nelle vicinanze

Seleziona un tipo di luogo dal menu per visualizzare i risultati di ricerca nelle vicinanze per quel tipo di luogo.

La ricerca nelle vicinanze è configurata principalmente per la ricerca in base al tipo di luogo e alla posizione. I risultati possono essere classificati in base alla distanza o alla popolarità utilizzando la proprietà rankPreference. Per ulteriori dettagli, consulta la documentazione di riferimento della classe PlaceNearbySearchRequestElement.

Questo esempio esegue il rendering dell'elemento Place Search in risposta a una Nearby Search con un tipo di luogo selezionato dall'utente. Visualizza anche un elemento PlaceDetailsCompactElement per il luogo selezionato.

Visualizza l'esempio di codice completo

Per aggiungere l'elemento Place Search alla mappa, aggiungi un elemento gmp-place-search con un elemento gmp-place-nearby-search-request nidificato alla pagina HTML.

<gmp-place-search selectable>
    <gmp-place-all-content></gmp-place-all-content>
    <gmp-place-nearby-search-request
        max-result-count="5"></gmp-place-nearby-search-request>
</gmp-place-search>

L'elemento select consente all'utente di scegliere un tipo di luogo dal menu. Per semplicità, sono elencati solo tre tipi di luoghi: ristorante, bar e stazione di ricarica EV.

<div class="controls">
    <label for="type-select">
        Select a place type:
        <select id="type-select" class="type-select">
            <option value="restaurant">Restaurant</option>
            <option value="cafe" selected>Cafe</option>
            <option value="electric_vehicle_charging_station">
                EV charging station
            </option>
        </select>
    </label>
</div>

Quando l'utente seleziona un tipo di luogo dal menu, l'elemento gmp-place-nearby-search-request viene aggiornato e l'elemento Place Search visualizza i risultati, come mostrato negli snippet seguenti. I marker vengono aggiunti nella funzione helper addMarkers.

// Add event listeners to the type select and place search elements.
    typeSelect.addEventListener('change', () => {
        searchPlaces();
    });

    placeSearch.addEventListener('gmp-select', (event) => {
        const { place } = event;
        markers.get(place.id)?.click();
    });
    placeSearch.addEventListener('gmp-load', () => {
        void addMarkers();
    });

    searchPlaces();
}
// The searchPlaces function is called when the user changes the type select or when the page loads.
function searchPlaces() {
    // Close the info window and clear the markers.
    infoWindow.close();
    for (const marker of markers.values()) {
        marker.remove();
    }
    markers.clear();

    // Set the place search query and add an event listener to the place search element.
    if (typeSelect.value) {
        const center = map.center;
        placeSearchQuery.locationRestriction = {
            center,
            radius: 50000, // 50km radius
        };
        placeSearchQuery.includedTypes = [typeSelect.value];
    }
}

Esempio di codice completo

JavaScript

// Query selectors for various elements in the HTML file.
const map = document.querySelector('gmp-map');
const placeSearch = document.querySelector('gmp-place-search');
const placeSearchQuery = document.querySelector(
    'gmp-place-nearby-search-request'
);
const placeDetails = document.querySelector('gmp-place-details-compact');
const placeRequest = document.querySelector('gmp-place-details-place-request');
const typeSelect = document.querySelector('.type-select');

// Global variables for the map, markers, and info window.
const markers = new Map();
let infoWindow;

// The init function is called when the page loads.
async function init() {
    // Import the necessary libraries from the Google Maps API.
    const [{ InfoWindow }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
    ]);

    // Create a new info window and set its content to the place details element.
    placeDetails.remove(); // Hide the place details element because it is not needed until the info window opens
    infoWindow = new InfoWindow({
        content: placeDetails,
        ariaLabel: 'Place Details',
    });

    // Set the map options.
    map.innerMap.setOptions({
        clickableIcons: false,
        mapTypeControl: false,
        streetViewControl: false,
    });

    // Add event listeners to the type select and place search elements.
    typeSelect.addEventListener('change', () => {
        searchPlaces();
    });

    placeSearch.addEventListener('gmp-select', (event) => {
        const { place } = event;
        markers.get(place.id)?.click();
    });
    placeSearch.addEventListener('gmp-load', () => {
        void addMarkers();
    });

    searchPlaces();
}
// The searchPlaces function is called when the user changes the type select or when the page loads.
function searchPlaces() {
    // Close the info window and clear the markers.
    infoWindow.close();
    for (const marker of markers.values()) {
        marker.remove();
    }
    markers.clear();

    // Set the place search query and add an event listener to the place search element.
    if (typeSelect.value) {
        const center = map.center;
        placeSearchQuery.locationRestriction = {
            center,
            radius: 50000, // 50km radius
        };
        placeSearchQuery.includedTypes = [typeSelect.value];
    }
}

// The addMarkers function is called when the place search element loads.
async function addMarkers() {
    // Import the necessary libraries from the Google Maps API.
    const [{ AdvancedMarkerElement }, { LatLngBounds }] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('core'),
    ]);
    const bounds = new LatLngBounds();

    if (placeSearch.places.length === 0) {
        return;
    }

    for (const place of placeSearch.places) {
        if (!place.location) continue;
        const marker = new AdvancedMarkerElement({
            map: map.innerMap,
            position: place.location,
            collisionBehavior: 'REQUIRED_AND_HIDES_OPTIONAL',
            gmpClickable: true,
        });

        markers.set(place.id, marker);
        bounds.extend(place.location);

        marker.addEventListener('gmp-click', () => {
            placeRequest.place = place;
            infoWindow.open(map.innerMap, marker);
        });
    }

    map.innerMap.fitBounds(bounds);
}

void init();

CSS

html,
body {
    height: 100%;
    margin: 0;
}

body {
    display: flex;
    flex-direction: column;
    font-family: Arial, Helvetica, sans-serif;
}

.container {
    display: flex;
    height: 100vh;
    width: 100%;
}

gmp-map {
    flex-grow: 1;
}

.ui-panel {
    width: 400px;
    margin-left: 20px;
    margin-top: 10px;
    overflow-y: auto;
    font-family: Arial, Helvetica, sans-serif;
}

.list-container {
    display: flex;
    flex-direction: column;
}

gmp-place-search {
    width: 100%;
    margin: 0;
    border: none;
    color-scheme: light;
}

HTML

<!doctype html>
<html>
    <head>
        <title>Place Search Nearby with Google Maps</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" type="text/css" href="style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (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: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>

        <div class="container">
            <!-- map-id is required to use advanced markers. See https://developers.google.com/maps/documentation/javascript/map-ids/mapid-over. -->
            <gmp-map center="-37.813,144.963" zoom="16" map-id="DEMO_MAP_ID">
            </gmp-map>
            <div class="ui-panel">
                <div class="controls">
                    <label for="type-select">
                        Select a place type:
                        <select id="type-select" class="type-select">
                            <option value="restaurant">Restaurant</option>
                            <option value="cafe" selected>Cafe</option>
                            <option value="electric_vehicle_charging_station">
                                EV charging station
                            </option>
                        </select>
                    </label>
                </div>
                <div class="list-container">
                    <gmp-place-search selectable>
                        <gmp-place-all-content></gmp-place-all-content>
                        <gmp-place-nearby-search-request
                            max-result-count="5"></gmp-place-nearby-search-request>
                    </gmp-place-search>
                </div>
            </div>
        </div>

        <!--
        The gmp-place-details-compact element is styled inline because it is
        conditionally rendered and moved into the info window, which is
        part of the map's shadow DOM.
    -->
        <gmp-place-details-compact
            orientation="horizontal"
            truncation-preferred
            style="
                width: 400px;
                padding: 0;
                margin: 0;
                border: none;
                background-color: transparent;
                color-scheme: light;
            ">
            <gmp-place-details-place-request></gmp-place-details-place-request>
            <gmp-place-content-config>
                <gmp-place-media></gmp-place-media>
                <gmp-place-rating></gmp-place-rating>
                <gmp-place-price></gmp-place-price>
                <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
                <gmp-place-open-now-status></gmp-place-open-now-status>
                <gmp-place-attribution
                    light-scheme-color="gray"
                    dark-scheme-color="white"></gmp-place-attribution>
            </gmp-place-content-config>
        </gmp-place-details-compact>

    </body>
</html>

Richiesta di ricerca per testo

Inserisci un termine di ricerca nel campo di immissione e fai clic sul pulsante Cerca per visualizzare un elenco di luoghi corrispondenti al termine.

La ricerca testuale è configurata principalmente per eseguire ricerche utilizzando una query di testo e una località. I risultati possono essere perfezionati in base al livello di prezzo, alla valutazione e allo stato di apertura. I risultati possono anche essere classificati in base alla distanza o alla popolarità utilizzando la proprietà rankPreference. Per ulteriori dettagli, consulta la documentazione di riferimento della classe PlaceTextSearchRequestElement.

Questo esempio esegue il rendering dell'elemento Place Search in risposta a un input di testo dell'utente. Visualizza anche un elemento PlaceDetailsCompactElement per il luogo selezionato.

Visualizza l'esempio di codice completo

Per aggiungere l'elemento Place Search alla mappa, aggiungi un elemento gmp-place-search con un elemento gmp-place-text-search-request nidificato alla pagina HTML.

<gmp-place-search selectable>
    <gmp-place-all-content></gmp-place-all-content>
    <gmp-place-text-search-request
        max-result-count="5"></gmp-place-text-search-request>
</gmp-place-search>

L'elemento input consente all'utente di inserire il testo di ricerca.

<div class="controls">
    <input
        type="text"
        id="query-input"
        class="query-input"
        placeholder="Search for a place"
        value="cafe" />
    <button id="search-button" class="search-button">
        Search
    </button>
</div>

Quando l'utente fa clic sul pulsante Cerca, viene eseguita la funzione di ricerca, l'elemento gmp-place-text-search-request viene aggiornato e l'elemento Place Search visualizza i risultati come mostrato nei seguenti snippet. I marker vengono aggiunti nella funzione helper addMarkers.

// Add event listeners to the query input and place search elements.
    searchButton.addEventListener('click', () => {
        searchPlaces();
    });
    queryInput.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
            searchPlaces();
        }
    });

    placeSearch.addEventListener('gmp-select', (event) => {
        const { place } = event;
        markers.get(place.id)?.click();
    });
    placeSearch.addEventListener('gmp-load', () => {
        void addMarkers();
    });

    searchPlaces();
}
// The searchPlaces function is called when the user changes the query input or when the page loads.
function searchPlaces() {
    // Close the info window and clear the markers.
    infoWindow.close();
    for (const marker of markers.values()) {
        marker.remove();
    }
    markers.clear();

    // Set the place search query and add an event listener to the place search element.
    if (queryInput.value) {
        const center = map.center;
        if (center) {
            placeSearchQuery.locationBias = center;
        }
        // The textQuery property is required for the search element to load.
        // Any other configured properties will be ignored if textQuery is not set.
        placeSearchQuery.textQuery = queryInput.value;
    }
}

Esempio di codice completo

JavaScript

// Query selectors for various elements in the HTML file.
const map = document.querySelector('gmp-map');
const placeSearch = document.querySelector('gmp-place-search');
const placeSearchQuery = document.querySelector(
    'gmp-place-text-search-request'
);
const placeDetails = document.querySelector('gmp-place-details-compact');
const placeRequest = document.querySelector('gmp-place-details-place-request');
const queryInput = document.querySelector('.query-input');
const searchButton = document.querySelector('.search-button');

// Global variables for the map, markers, and info window.
const markers = new Map();
let infoWindow;

// The init function is called when the page loads.
async function init() {
    // Import the necessary libraries from the Google Maps API.
    const [{ InfoWindow }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
    ]);

    // Create a new info window and set its content to the place details element.
    placeDetails.remove(); // Hide the place details element because it is not needed until the info window opens
    infoWindow = new InfoWindow({
        content: placeDetails,
        ariaLabel: 'Place Details',
    });

    // Set the map options.
    map.innerMap.setOptions({
        clickableIcons: false,
        mapTypeControl: false,
        streetViewControl: false,
    });

    // Add event listeners to the query input and place search elements.
    searchButton.addEventListener('click', () => {
        searchPlaces();
    });
    queryInput.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
            searchPlaces();
        }
    });

    placeSearch.addEventListener('gmp-select', (event) => {
        const { place } = event;
        markers.get(place.id)?.click();
    });
    placeSearch.addEventListener('gmp-load', () => {
        void addMarkers();
    });

    searchPlaces();
}
// The searchPlaces function is called when the user changes the query input or when the page loads.
function searchPlaces() {
    // Close the info window and clear the markers.
    infoWindow.close();
    for (const marker of markers.values()) {
        marker.remove();
    }
    markers.clear();

    // Set the place search query and add an event listener to the place search element.
    if (queryInput.value) {
        const center = map.center;
        if (center) {
            placeSearchQuery.locationBias = center;
        }
        // The textQuery property is required for the search element to load.
        // Any other configured properties will be ignored if textQuery is not set.
        placeSearchQuery.textQuery = queryInput.value;
    }
}

// The addMarkers function is called when the place search element loads.
async function addMarkers() {
    // Import the necessary libraries from the Google Maps API.
    const [{ AdvancedMarkerElement }, { LatLngBounds }] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('core'),
    ]);
    const bounds = new LatLngBounds();

    if (placeSearch.places.length === 0) {
        return;
    }

    for (const place of placeSearch.places) {
        if (!place.location) {
            continue;
        }

        const marker = new AdvancedMarkerElement({
            map: map.innerMap,
            position: place.location,
            collisionBehavior: 'REQUIRED_AND_HIDES_OPTIONAL',
            gmpClickable: true,
        });

        markers.set(place.id, marker);
        bounds.extend(place.location);

        marker.addEventListener('gmp-click', () => {
            placeRequest.place = place;
            infoWindow.open(map.innerMap, marker);
        });
    }

    map.innerMap.fitBounds(bounds);
}

void init();

CSS

html,
body {
    height: 100%;
    margin: 0;
}

body {
    display: flex;
    flex-direction: column;
    font-family: Arial, Helvetica, sans-serif;
}

.container {
    display: flex;
    height: 100vh;
    width: 100%;
}

gmp-map {
    flex-grow: 1;
}

.ui-panel {
    width: 400px;
    margin-left: 20px;
    margin-right: 20px;
    margin-top: 10px;
    overflow-y: auto;
    font-family: Arial, Helvetica, sans-serif;
}

.list-container {
    display: flex;
    flex-direction: column;
}

gmp-place-search {
    width: 100%;
    margin: 0;
    border: none;
    color-scheme: light;
}

.query-input {
    width: 100%;
    padding: 8px;
    margin-bottom: 10px;
    box-sizing: border-box;
}

.search-button {
    width: 100%;
    padding: 8px;
    margin-bottom: 10px;
    box-sizing: border-box;
    background-color: #1a73e8;
    color: white;
    border: none;
    cursor: pointer;
}

.search-button:hover,
.search-button:focus-visible {
    background-color: #1765cc;
}

HTML

<!doctype html>
<html>
    <head>
        <title>Place Text Search with Google Maps</title>
        <meta charset="utf-8" />
        <link rel="stylesheet" type="text/css" href="style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (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: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>

        <div class="container">
            <div class="ui-panel">
                <div class="controls">
                    <input
                        type="text"
                        id="query-input"
                        class="query-input"
                        placeholder="Search for a place"
                        value="cafe" />
                    <button class="search-button">Search</button>
                </div>
                <div class="list-container">
                    <gmp-place-search selectable>
                        <gmp-place-all-content></gmp-place-all-content>
                        <gmp-place-text-search-request
                            max-result-count="5"></gmp-place-text-search-request>
                    </gmp-place-search>
                </div>
            </div>
            <!-- map-id is required to use advanced markers. See https://developers.google.com/maps/documentation/javascript/map-ids/mapid-over. -->
            <gmp-map center="-37.813,144.963" zoom="16" map-id="DEMO_MAP_ID">
            </gmp-map>
        </div>

        <!--
        The gmp-place-details-compact element is styled inline because it is
        conditionally rendered and moved into the info window, which is
        part of the map's shadow DOM.
        -->
        <gmp-place-details-compact
            orientation="horizontal"
            truncation-preferred
            style="
                width: 400px;
                padding: 0;
                margin: 0;
                border: none;
                background-color: transparent;
                color-scheme: light;
            ">
            <gmp-place-details-place-request></gmp-place-details-place-request>
            <gmp-place-content-config>
                <gmp-place-media></gmp-place-media>
                <gmp-place-rating></gmp-place-rating>
                <gmp-place-price></gmp-place-price>
                <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
                <gmp-place-open-now-status></gmp-place-open-now-status>
                <gmp-place-attribution
                    light-scheme-color="gray"
                    dark-scheme-color="white"></gmp-place-attribution>
            </gmp-place-content-config>
        </gmp-place-details-compact>

    </body>
</html>

Configura i contenuti

Gli snippet in questa pagina utilizzano gmp-place-all-content per mostrare tutti i contenuti disponibili per ogni luogo nei risultati. Per mostrare invece un set di standard di contenuti, utilizza gmp-place-standard-content.

Per scegliere contenuti specifici, aggiungi un elemento <template slot="details-item"> all'elemento gmp-place-search e inserisci gli elementi dei contenuti da mostrare per ogni luogo all'interno del modello. Vengono visualizzati solo gli elementi dei contenuti che includi, quindi includi gmp-place-name per mostrare il nome di ogni luogo. Per configurare l'attribuzione, aggiungi un elemento gmp-place-attribution come elemento secondario diretto di gmp-place-search, all'esterno del modello.

<gmp-place-search selectable>
  <gmp-place-text-search-request text-query="pizza" max-result-count="5"></gmp-place-text-search-request>
  <template slot="details-item">
    <gmp-place-name></gmp-place-name>
    <gmp-place-media></gmp-place-media>
    <gmp-place-rating></gmp-place-rating>
    <gmp-place-address></gmp-place-address>
  </template>
  <gmp-place-attribution light-scheme-color="black" dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-search>

Per saperne di più su tutti gli elementi dei contenuti supportati, consulta la documentazione di riferimento sulla personalizzazione dei contenuti dei Place Widget.