Descobrir lugares com o elemento de pesquisa de lugar e a API Maps JavaScript

Objetivo

Aprenda a integrar o elemento Place Search ao Google Maps para ajudar os usuários a encontrar lugares usando a pesquisa por perto ou de texto, melhorando a capacidade deles de explorar pontos de interesse. Use o elemento Place Details Compact para fornecer mais detalhes sobre os lugares que aparecem no seu aplicativo.

O que é o elemento Place Search?

O elemento Place Search faz parte do Kit de Interface do Places na API Maps JavaScript. É um elemento HTML que renderiza os resultados de uma pesquisa de lugar diretamente em um formato de lista no seu aplicativo. Esse elemento simplifica o processo de exibição de Places encontrados usando uma Nearby Search ou uma Text Search, proporcionando uma experiência do usuário perfeita para a descoberta de Places. Quando um usuário seleciona um lugar na lista, você pode mostrar os detalhes dele no mapa, geralmente usando uma janela de informações e o elemento Place Details.

Visualizar a descoberta de lugares

A imagem a seguir mostra um exemplo do elemento Place Search em ação. À esquerda, uma lista de restaurantes é mostrada (o elemento Place Search). Quando um restaurante é selecionado, os detalhes dele aparecem em uma janela de informações no mapa, e o mapa é centralizado no local.

imagem

Casos de uso para descoberta de lugares

A integração do elemento Place Search pode melhorar vários aplicativos em diferentes setores:

  • Viagens e turismo:permita que os turistas pesquisem atrações, hotéis ou tipos específicos de culinária em uma área.
  • Imóveis:permita que compradores ou locatários em potencial encontrem escolas, supermercados ou opções de transporte público nas proximidades.
  • Logística e serviços:ajude os motoristas a encontrar eletropostos, postos de gasolina ou centros de serviço específicos.

Fluxo de trabalho da solução: implementação da descoberta de lugares

Esta seção explica as etapas para integrar o elemento Place Search para descobrir lugares em um mapa, incluindo snippets de código para interagir com o Kit de Interface do Places. Vamos abordar a inicialização do mapa e a implementação das funcionalidades de Nearby Search e Text Search. Por fim, vamos usar o elemento Place Details para mostrar mais detalhes sobre um lugar específico, ao clicar no alfinete dele no mapa.

Pré-requisitos

Recomendamos que você esteja familiarizado com a seguinte documentação:

Ative a API Maps JavaScript e o Kit de Interface do Places no seu projeto.

Verifique se você carregou a API Maps JavaScript e importou as bibliotecas necessárias antes de começar. Este documento também pressupõe um conhecimento prático de desenvolvimento da Web, incluindo HTML, CSS e JavaScript.

Adicionar um mapa à página

A primeira etapa é adicionar um mapa à sua página. Esse mapa será usado para mostrar os resultados do elemento Place Search como alfinetes selecionáveis.

Há duas maneiras de adicionar um mapa a uma página:

  1. Usando um gmp-map componente da Web HTML.
  2. Usando JavaScript.

Os snippets de código nesta página foram gerados usando um mapa JavaScript.

O mapa pode ser centralizado em um local em que você quer que o usuário pesquise, como um hotel, ou inicializado para pedir a localização atual do usuário para centralizar o mapa. Para fins deste documento, vamos usar um local fixo para ancorar a pesquisa.

Se você estiver visualizando lugares próximos a um local fixo, como um hotel, coloque um marcador no mapa para representar esse lugar. Por exemplo:

imagem

O mapa está centralizado em São Francisco, com um alfinete azul para representar o lugar que estamos pesquisando nas proximidades. A cor do alfinete foi personalizada usando PinElement. O controle de tipo de mapa foi ocultado da interface.

Configurar o elemento Place Search

Agora, podemos configurar o HTML e o CSS para mostrar o elemento Place Search. Para este exemplo, vamos flutuar o elemento sobre o lado esquerdo do mapa, mas recomendamos que você tente layouts diferentes para adequar ao seu aplicativo.

O elemento Place Search usa uma abordagem declarativa. Em vez de configurá-lo totalmente em JavaScript, você define o tipo de pesquisa diretamente no HTML aninhando um elemento de solicitação, como <gmp-place-nearby-search-request>, dentro do componente principal <gmp-place-search> component.

No código HTML, inicialize um elemento <gmp-place-search>. Use o atributo selectable para ativar eventos de clique nos resultados. Dentro dele, adicione um <gmp-place-nearby-search-request> para especificar que esse elemento será usado para pesquisa por perto.

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

Para realizar uma pesquisa inicial e mostrar os resultados, vamos usar JavaScript para receber uma referência ao elemento de solicitação aninhado e definir as propriedades dele. Inicialize um círculo para usar como locationRestriction, usando a posição do marcador da etapa anterior como o ponto central. Em seguida, defina as propriedades locationRestriction e includedPrimaryTypes no elemento de solicitação para acionar a pesquisa.

O snippet de código para isso é o seguinte:

// 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'];

Confira um exemplo de como o aplicativo pode ficar nessa fase:

imagem

O elemento Place Search permite duas opções de pesquisa:

Esses são elementos aninhados dentro de <gmp-place-search>. Em seguida, você aciona as pesquisas definindo propriedades nesse elemento de solicitação aninhado usando JavaScript.

Esta seção descreve a implementação dos dois métodos.

imagem

Para permitir que os usuários façam uma pesquisa por perto, primeiro você precisa de um elemento da interface para que eles selecionem um tipo de lugar. Escolha o método de seleção que funciona melhor para seu aplicativo, por exemplo, uma lista suspensa preenchida com uma seleção de tipos de lugares.

Recomendamos escolher um subconjunto de tipos relevantes para seu caso de uso. Por exemplo, se você estiver desenvolvendo um aplicativo para mostrar aos turistas o que está perto de um hotel, poderá escolher: bakery, coffee_shop, museum, restaurant e tourist_attraction.

O HTML precisa conter o elemento <gmp-place-search> com um <gmp-place-nearby-search-request> aninhado dentro.

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

Em seguida, crie um listener JavaScript para o evento change no seletor de tipo de lugar. Esse listener vai chamar uma função que atualiza as propriedades do <gmp-place-nearby-search-request> elemento, que aciona automaticamente uma nova pesquisa e atualiza a lista.

// 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];
}

O mesmo searchCircle da etapa de configuração é usado para locationRestriction. A propriedade includedPrimaryTypes é definida como o valor da seleção do usuário. Um maxResultCount opcional também é definido para limitar o número de resultados.

imagem

Para ativar a pesquisa de texto, a configuração HTML precisa mudar. Em vez da solicitação de pesquisa por perto, você aninha um <gmp-place-text-search-request> elemento.

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

Adicione uma entrada de texto e um botão de pesquisa à interface. Crie um listener JavaScript para o evento click do botão. O manipulador de eventos vai receber a entrada do usuário e atualizar as propriedades do <gmp-place-text-search-request> elemento para realizar a pesquisa.

// 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;
}

Aqui, definimos a propriedade textQuery com a entrada do usuário. Também fornecemos um locationBias usando os limites atuais do mapa, que informa à API para preferir resultados nessa área sem restringi-los estritamente. Um maxResultCount opcional limita o número de resultados retornados.

Mostrar alfinetes e detalhes do lugar

Agora, o aplicativo pode realizar uma pesquisa de lugar e preencher o elemento. Na próxima etapa, vamos melhorar a funcionalidade dele:

  • Mostrar alfinetes no mapa para cada lugar preenchido no elemento Place Search.
  • Permitir que um usuário clique em um alfinete ou no lugar dentro do elemento Place Search para mostrar mais detalhes sobre esse lugar específico.

O princípio dessa etapa é o mesmo, seja o aplicativo usando uma pesquisa por perto ou de texto.

Primeiro, adicione uma variável global ao código JavaScript para armazenar os marcadores de lugar. Isso permite que você os remova quando a pesquisa mudar e processe eventos de clique.

let markers = {};

Crie uma função para adicionar marcadores ao mapa. Essa função será chamada sempre que novos resultados de pesquisa forem carregados. Ela vai:

  • Remover todos os marcadores de lugar existentes do mapa.
  • Fazer um loop nos resultados do elemento Place Search e adicionar um marcador para cada um.
  • Ajustar os limites do mapa para que todos os novos marcadores fiquem visíveis.

Para detectar quando os resultados da pesquisa estão disponíveis, adicione um gmp-load listener de eventos ao elemento <gmp-place-search>. Esse evento é acionado depois que uma pesquisa é concluída e os resultados são renderizados.

Vamos adicionar o listener dentro da nossa função de pesquisa (por exemplo, updatePlaceList) e usar a opção { once: true } para garantir que ele seja acionado apenas para os resultados da pesquisa atual.

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

A função addMarkers é assim:

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);
    }
}

Depois que essa etapa for concluída, o aplicativo vai ficar assim, com a capacidade de mostrar marcadores para cada lugar retornado pelo elemento Place Search:

imagem

Agora que temos marcadores no mapa, a última etapa é processar eventos de clique de marcador e elemento para mostrar uma janela de informações com detalhes do lugar, fornecidos pelo elemento Place Details. Para este exemplo, vamos usar o elemento Place Details Compact.

Adicione o HTML do elemento Place Details Compact ao seu código, por exemplo:

<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>

O style está definido como display: none; ele não ficará visível até ser necessário. gmp-place-all-content é transmitido para renderizar todo o conteúdo do elemento. Para escolher qual conteúdo renderizar, consulte a documentação do elemento Place Details Compact.

Crie uma variável global em JavaScript para manter uma referência ao elemento Place Details Compact e preencha-a no código de inicialização, por exemplo:

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

Na função addMarkers, adicione um listener de eventos gmp-click a cada marcador e configure o elemento Place Details Compact para mostrar os detalhes do lugar transmitindo o ID do lugar do marcador atual.

Depois disso, uma janela de informações será aberta para mostrar o elemento Place Details Compact, ancorado no marcador.

Por fim, o mapa é posicionado na janela de visualização do lugar selecionado, tornando-o visível.

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 });
                });
            });
          ...
        });
    }
}

Para permitir que o usuário clique em um lugar no elemento Place List para mostrar o elemento Place Details Compact, adicione o seguinte ao código JavaScript após a chamada para configureFromSearchNearbyRequest.

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

Depois que essa etapa for concluída, o aplicativo poderá usar uma Nearby Search ou Text Search para preencher o elemento Place List. Os resultados vão mostrar alfinetes no mapa, e clicar em um alfinete ou em um lugar no elemento Place List vai mostrar uma janela de informações com detalhes do lugar, fornecidos pelo elemento Place Details Compact.

O aplicativo vai ficar assim:

imagem

Conclusão

O elemento Place Search combinado com o elemento Place Details Compact oferece uma maneira simplificada de adicionar recursos avançados de descoberta de lugares aos seus aplicativos da Plataforma Google Maps.

Teste o Kit de Interface do Places hoje mesmo para permitir que seus usuários encontrem e explorem lugares usando pesquisas por perto e de texto e mostre detalhes avançados do lugar, melhorando a interação deles com seus casos de uso de descoberta de lugares.

Colaboradores

Henrik Valve | Engenheiro de DevX