Scoprire luoghi con l'elemento di ricerca di luoghi e l'API Maps JavaScript

Obiettivo

Scopri come integrare l'elemento Place Search con Google Maps per aiutare gli utenti a trovare luoghi utilizzando la ricerca nelle vicinanze o la ricerca testuale, migliorando la loro capacità di esplorare i punti di interesse. Utilizza l'elemento Place Details Compact per fornire maggiori dettagli sui luoghi visualizzati nella tua applicazione.

Che cos'è l'elemento Place Search?

L'elemento Place Search fa parte di Places UI Kit nell'API Maps JavaScript. È un elemento HTML che esegue il rendering dei risultati di una ricerca di luoghi direttamente in un formato di elenco all'interno dell'applicazione. Questo elemento semplifica la visualizzazione dei luoghi trovati utilizzando una Nearby Search o una Ricerca testuale, fornendo un'esperienza utente fluida per la scoperta dei luoghi. Quando un utente seleziona un luogo dall'elenco, puoi visualizzarne i dettagli sulla mappa, spesso utilizzando una finestra informativa e l'elemento Place Details.

Visualizzare la scoperta dei luoghi

L'immagine seguente mostra un esempio dell'elemento Place Search in azione. A sinistra viene visualizzato un elenco di ristoranti (l'elemento Place Search). Quando viene selezionato un ristorante, i relativi dettagli vengono visualizzati in una finestra informativa sulla mappa e la mappa viene centrata sulla sua posizione.

immagine

Casi d'uso per la scoperta dei luoghi

L'integrazione dell'elemento Place Search può migliorare varie applicazioni in diversi settori:

  • Viaggi e turismo: consente ai turisti di cercare attrazioni, hotel o tipi specifici di cucina in una zona.
  • Immobili: consente a potenziali acquirenti o affittuari di trovare scuole, supermercati o opzioni di trasporto pubblico nelle vicinanze.
  • Logistica e servizi: aiuta i conducenti a trovare stazioni di ricarica EV, stazioni di servizio o centri di assistenza specifici.

Flusso di lavoro della soluzione: implementare la scoperta dei luoghi

Questa sezione illustra i passaggi per integrare l'elemento Place Search per scoprire i luoghi su una mappa, inclusi snippet di codice per interagire con Places UI Kit. Tratteremo l'inizializzazione della mappa e l'implementazione delle funzionalità di Nearby Search e Ricerca testuale. Infine, utilizzeremo l'elemento Place Details per mostrare maggiori dettagli su un luogo specifico, quando si fa clic sul relativo segnaposto sulla mappa.

Prerequisiti

È consigliabile conoscere la seguente documentazione:

Attiva Maps JavaScript API e Places UI Kit nel tuo progetto.

Prima di iniziare, verifica di aver caricato l'API Maps JavaScript e di aver importato le librerie richieste. Questo documento presuppone anche una conoscenza pratica dello sviluppo web, inclusi HTML, CSS e JavaScript.

Aggiungere una mappa alla pagina

Il primo passo è aggiungere una mappa alla pagina. Questa mappa verrà utilizzata per visualizzare i risultati dell'elemento Place Search come segnaposti selezionabili.

Esistono due modi per aggiungere una mappa a una pagina:

  1. Utilizzando un gmp-map componente web HTML.
  2. Utilizzando JavaScript.

Gli snippet di codice in questa pagina sono stati generati utilizzando una mappa JavaScript.

La mappa può essere centrata su una località in cui l'utente deve eseguire la ricerca, ad esempio un hotel, oppure inizializzata per chiedere la posizione corrente dell'utente per centrare la mappa. Ai fini di questo documento, utilizzeremo una posizione fissa per ancorare la ricerca.

Se visualizzi i luoghi nelle vicinanze di una posizione fissa, ad esempio un hotel, inserisci un indicatore sulla mappa per rappresentare questo luogo. Ad esempio:

immagine

La mappa è centrata su San Francisco, con un segnaposto blu che rappresenta il luogo in cui stiamo cercando nelle vicinanze. Il colore del segnaposto è stato personalizzato utilizzando PinElement. Il controllo Tipo di mappa è stato nascosto dall'interfaccia utente.

Configurare l'elemento Place Search

Ora possiamo configurare l'HTML e il CSS per visualizzare l'elemento Place Search. Per questo esempio, faremo fluttuare l'elemento sul lato sinistro della mappa, ma ti consigliamo di provare layout diversi per adattarli alla tua applicazione.

L'elemento Place Search utilizza un approccio dichiarativo. Anziché configurarlo interamente in JavaScript, definisci il tipo di ricerca direttamente in HTML nidificando un elemento di richiesta, ad esempio <gmp-place-nearby-search-request>, all'interno del componente <gmp-place-search> principale.

All'interno del codice HTML, inizializza un elemento <gmp-place-search>. Utilizza l'attributo selectable per attivare gli eventi di clic sui risultati. Al suo interno, aggiungi un <gmp-place-nearby-search-request> per specificare che questo elemento verrà utilizzato per la ricerca nelle vicinanze.

<gmp-place-search selectable>
  <gmp-place-nearby-search-request>
  </gmp-place-nearby-search-request>
</gmp-place-search>

Per eseguire una ricerca iniziale e visualizzare i risultati, utilizzeremo JavaScript per ottenere un riferimento all'elemento di richiesta nidificato e impostarne le proprietà. Inizializza un cerchio da utilizzare come locationRestriction, utilizzando la posizione dell'indicatore del passaggio precedente come punto centrale. Poi, imposta le proprietà locationRestriction e includedPrimaryTypes sull'elemento di richiesta per attivare la ricerca.

Lo snippet di codice è il seguente:

// Get references to the Place Search and its nested request element
const placeSearchElement = document.querySelector("gmp-place-search");
const placeSearchRequestElement = document.querySelector("gmp-place-nearby-search-request");

// Define the location restriction for the search
const circleRestriction = new Circle({
    center: marker.position,
    radius: 500
});

// Set the properties on the request element to perform an initial search for restaurants.
placeSearchRequestElement.locationRestriction = circleRestriction;
placeSearchRequestElement.includedPrimaryTypes = ['restaurant'];

Di seguito è riportato un esempio di come potrebbe apparire l'applicazione in questa fase:

immagine

L'elemento Place Search consente due opzioni di ricerca:

  • <gmp-place-nearby-search-request> - esegue il rendering dei risultati di ricerca da una Nearby Search, utilizzando i tipi di luoghi.
  • <gmp-place-text-search-request> - esegue il rendering dei risultati di ricerca da una Ricerca testuale di Places, utilizzando un input di testo libero come "Sushi a San Francisco".

Questi sono elementi nidificati all'interno di <gmp-place-search>. Poi, attivi le ricerche impostando le proprietà dell'elemento di richiesta nidificato utilizzando JavaScript.

Questa sezione descrive l'implementazione di entrambi i metodi.

immagine

Per consentire agli utenti di eseguire una ricerca nelle vicinanze, devi prima avere un elemento dell'interfaccia utente per loro per selezionare un tipo di luogo. Scegli il metodo di selezione più adatto alla tua applicazione, ad esempio un elenco a discesa popolato con una selezione di tipi di luoghi.

Ti consigliamo di scegliere un sottoinsieme di tipi pertinenti al tuo caso d'uso. Ad esempio, se stai sviluppando un'applicazione per mostrare ai turisti cosa si trova nelle vicinanze di un hotel, potresti scegliere: bakery, coffee_shop, museum, restaurant e tourist_attraction.

L'HTML deve contenere l'elemento <gmp-place-search> con un <gmp-place-nearby-search-request> nidificato al suo interno.

<gmp-place-search selectable>
  <gmp-place-nearby-search-request>
  </gmp-place-nearby-search-request>
</gmp-place-search>

Poi, crea un listener JavaScript per l'evento change sul selettore del tipo di luogo. Questo listener chiamerà una funzione che aggiorna le proprietà dell' <gmp-place-nearby-search-request> elemento, che attiva automaticamente una nuova ricerca e aggiorna l'elenco.

// Get a reference to the nested request element
const placeSearchRequestElement = document.querySelector('gmp-place-nearby-search-request');

// Function to update the place search based on the selected type
function updatePlaceList() {
    const selectedType = placeTypeSelect.value;
    if (!selectedType) {
        // If no type is selected, don't perform a search.
        // You could optionally hide the list or clear previous results here.
        placeSearchElement.style.display = 'none';
        return;
    }
    placeSearchElement.style.display = 'block';

    // Set properties on the request element to trigger a new search
    placeSearchRequestElement.locationRestriction = searchCircle;
    placeSearchRequestElement.maxResultCount = 8;
    placeSearchRequestElement.includedPrimaryTypes = [selectedType];
}

Lo stesso searchCircle del passaggio di configurazione viene utilizzato per locationRestriction. La proprietà includedPrimaryTypes è impostata sul valore della selezione dell'utente. Viene impostato anche un maxResultCount facoltativo per limitare il numero di risultati.

immagine

Per attivare la ricerca testuale, la configurazione HTML deve essere modificata. Anziché la richiesta di ricerca nelle vicinanze, nidifica un elemento <gmp-place-text-search-request>.

<gmp-place-search selectable>
  <gmp-place-text-search-request>
  </gmp-place-text-search-request>
</gmp-place-search>

Aggiungi un input di testo e un pulsante di ricerca all'interfaccia utente. Crea un listener JavaScript per l'evento click del pulsante. Il gestore di eventi prenderà l'input dell'utente e aggiornerà le proprietà dell'elemento <gmp-place-text-search-request> per eseguire la ricerca.

// Get a reference to the text search request element
const placeTextSearchRequestElement = document.querySelector('gmp-place-text-search-request');
const textSearchInput = document.getElementById('textSearchInput');
const textSearchButton = document.getElementById('textSearchButton');

textSearchButton.addEventListener('click', performTextSearch);

function performTextSearch() {
    const query = textSearchInput.value.trim();
    if (!query) {
        console.log("Search query is empty.");
        return;
    }
    // Set properties on the request element to trigger a new search
    placeTextSearchRequestElement.textQuery = query;
    placeTextSearchRequestElement.locationBias = map.getBounds();
    placeTextSearchRequestElement.maxResultCount = 8;
}

Qui, impostiamo la proprietà textQuery con l'input dell'utente. Forniamo anche un locationBias utilizzando i limiti della mappa corrente, che indica all'API di preferire i risultati all'interno di questa area senza confinarli rigorosamente. Un maxResultCount facoltativo limita il numero di risultati restituiti.

Visualizzare i segnaposti e i dettagli dei luoghi

Ora l'applicazione può eseguire una ricerca di luoghi e popolare l'elemento. Nel passaggio successivo ne miglioreremo la funzionalità:

  • Visualizzando i segnaposti sulla mappa per ogni luogo inserito nell'elemento Place Search.
  • Consentendo a un utente di fare clic su un segnaposto o sul luogo all'interno dell'elemento Place Search per visualizzare maggiori dettagli su quel luogo specifico.

Il principio di questo passaggio è lo stesso, indipendentemente dal fatto che l'applicazione utilizzi una ricerca nelle vicinanze o una ricerca testuale.

Innanzitutto, aggiungi una variabile globale al codice JavaScript per memorizzare i segnaposti dei luoghi. In questo modo potrai rimuoverli quando la ricerca cambia e gestire gli eventi di clic.

let markers = {};

Crea una funzione per aggiungere segnaposti alla mappa. Questa funzione verrà chiamata ogni volta che vengono caricati nuovi risultati di ricerca. Eseguirà le seguenti operazioni:

  • Rimuovi tutti i segnaposti dei luoghi esistenti dalla mappa.
  • Esegui un loop sui risultati dell'elemento Place Search e aggiungi un segnaposto per ognuno.
  • Regola i limiti della mappa in modo che tutti i nuovi segnaposti siano visibili.

Per ascoltare quando sono disponibili i risultati di ricerca, aggiungi un gmp-load listener di eventi all'<gmp-place-search> elemento. Questo evento viene attivato al termine di una ricerca e al rendering dei risultati.

Aggiungeremo il listener all'interno della nostra funzione di ricerca (ad es. updatePlaceList) e utilizzeremo l'opzione { once: true } per assicurarci che venga attivato solo per i risultati della ricerca corrente.

// In your search function, after setting the request properties:
placeSearchElement.addEventListener('gmp-load', addMarkers, { once: true });

La funzione addMarkers è la seguente:

async function addMarkers() {
    const { LatLngBounds } = await google.maps.importLibrary("core");
    const bounds = new LatLngBounds();

    if (placeSearchElement.places.length > 0) {
        // Remove existing markers
        for (const m in markers) {
            markers[m].map = null;
        }
        markers = {};

        // Loop through each place from the search results
        // and add a marker for each one.
        for (const place of placeSearchElement.places) {
            const marker = new google.maps.marker.AdvancedMarkerElement({
                map: map,
                position: place.location,
            });

            markers[place.id] = marker;
            bounds.extend(place.location);
            marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;

            // Add a click listener for each marker.
            marker.addListener('gmp-click', (event) => {
                // The main logic for showing details will go here.
            });
        }
        // Position the map to display all markers.
        map.setCenter(bounds.getCenter());
        map.fitBounds(bounds);
    }
}

Una volta completato questo passaggio, l'applicazione avrà il seguente aspetto, con la possibilità di mostrare i segnaposti per ogni luogo restituito dall'elemento Place Search:

immagine

Ora che abbiamo i segnaposti sulla mappa, l'ultimo passaggio consiste nel gestire gli eventi di clic sui segnaposti e sugli elementi per mostrare una finestra informativa con i dettagli del luogo, forniti dall'elemento Place Details. Per questo esempio, utilizzeremo l'elemento Place Details Compact Element.

Aggiungi l'HTML dell'elemento Place Details Compact al tuo codice, ad esempio:

<gmp-place-details-compact orientation="vertical" style="display: none;">
    <gmp-place-all-content></gmp-place-all-content>
    <gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-details-compact>

style è impostato su display: none; non sarà visibile finché non sarà necessario. Viene passato gmp-place-all-content per eseguire il rendering di tutti i contenuti degli elementi. Per scegliere i contenuti di cui eseguire il rendering, consulta la documentazione dell'elemento Place Details Compact Element Place Details Compact.

Crea una variabile globale in JavaScript per contenere un riferimento all'elemento Place Details Compact e inseriscila nel codice di inizializzazione, ad esempio:

let placeDetailsElement;
...
placeDetailsElement = document.querySelector('gmp-place-details-compact');

All'interno della funzione addMarkers, aggiungi un listener di eventi gmp-click a ogni segnaposto e configura l'elemento Place Details Compact per mostrare i dettagli del luogo passando l'ID luogo del segnaposto corrente.

Una volta completata questa operazione, viene aperta una finestra informativa per visualizzare l'elemento Place Details Compact, ancorato al segnaposto.

Infine, la mappa viene posizionata nell'area visibile del luogo selezionato, rendendola visibile.

async function addMarkers() {
          ...
            marker.addListener('gmp-click', (event) => {
                //Set up Place Details Compact Widget
                placeDetailsElement.style.display = "block";
                // Remove any existing place request element
                const existingPlaceRequest = placeDetailsElement.querySelector('gmp-place-details-place-request');
                if (existingPlaceRequest) {
                    existingPlaceRequest.remove();
                }
                // Create and configure the new place request element
                const placeRequestElement = new google.maps.places.PlaceDetailsPlaceRequestElement({ place: place.id });
                // Prepend the new place request element to the main widget
                placeDetailsElement.prepend(placeRequestElement);
                if (infoWindow.isOpen) {
                    infoWindow.close();
                }
                infoWindow.setOptions({
                    content: placeDetailsElement
                });
                infoWindow.open({
                    anchor: marker,
                    map: map
                });
                // Position the map to show the selected place
                placeDetailsElement.addEventListener('gmp-load', () => {
                    map.fitBounds(place.viewport, { top: 500, left: 400 });
                });
            });
          ...
        });
    }
}

Per consentire all'utente di fare clic su un luogo nell'elemento Place List per mostrare l'elemento Place Details Compact, aggiungi quanto segue al codice JavaScript dopo la chiamata a configureFromSearchNearbyRequest.

placeSearchElement.addEventListener("gmp-select", ({ place }) => {
    if (markers[place.id]) {
        markers[place.id].click();
    }
});

Una volta completato questo passaggio, l'applicazione sarà in grado di utilizzare una Nearby Search o una Ricerca testuale per popolare l'elemento Place List. I risultati mostreranno i segnaposti sulla mappa e, se fai clic su un segnaposto o su un luogo nell'elemento Place List, verrà visualizzata una finestra informativa con i dettagli del luogo, forniti dall'elemento Place Details Compact.

L'applicazione avrà il seguente aspetto:

immagine

Conclusione

L'elemento Place Search combinato con l'elemento Place Details Compact offre un modo semplificato per aggiungere funzionalità di scoperta dei luoghi avanzate alle tue applicazioni Google Maps Platform.

Prova Places UI Kit oggi stesso per consentire ai tuoi utenti di trovare ed esplorare i luoghi utilizzando le ricerche nelle vicinanze e testuali e di visualizzare dettagli avanzati sui luoghi, migliorando la loro interazione con i tuoi casi d'uso di scoperta dei luoghi.

Collaboratori

Henrik Valve | DevX Engineer