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

Objetivo

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

.

O que é o elemento de pesquisa de lugar?

O elemento de pesquisa de lugar 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 mostrar lugares encontrados usando uma pesquisa por proximidade ou de texto, oferecendo uma experiência de usuário perfeita para a descoberta de lugares. 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 de detalhes do lugar.

Visualizar a descoberta de lugares

A imagem a seguir mostra um exemplo do elemento de pesquisa de lugar em ação. À esquerda, uma lista de restaurantes é exibida (o elemento de pesquisa de lugar). 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 da descoberta de lugares

A integração do elemento de pesquisa de lugar pode melhorar vários aplicativos em diferentes setores:

  • Viagens e turismo:permite 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:ajuda os motoristas a encontrar eletropostos, postos de gasolina ou centros de serviços específicos.

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

Esta seção mostra as etapas para integrar o elemento de pesquisa de lugar 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 Pesquisa por proximidade e Pesquisa de texto. Por fim, vamos usar o elemento Place Details para mostrar mais detalhes sobre um lugar específico quando o usuário clicar no pino dele no mapa.

Pré-requisitos

Recomendamos que você se familiarize 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 à página. Esse mapa será usado para mostrar os resultados do elemento de pesquisa de lugar como alfinetes selecionáveis.

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

  1. Usando um componente da Web HTML gmp-map.
  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 que você quer que o usuário pesquise, como um hotel, ou inicializado para pedir o local atual do usuário e centralizar o mapa. Para fins deste documento, vamos usar um local fixo para ancorar a pesquisa.

Se você estiver visualizando lugares perto de um local fixo, como um hotel, coloque um marcador no mapa para representar esse lugar. 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 marcador foi personalizada usando PinElement. O controle de tipo de mapa foi ocultado da interface.

Configurar o elemento de pesquisa de lugar

Agora, podemos configurar o HTML e o CSS para mostrar o elemento de pesquisa de lugar. Para este exemplo, vamos flutuar o elemento sobre o lado esquerdo do mapa, mas é recomendável testar layouts diferentes para adequar ao seu aplicativo.

O elemento de pesquisa de lugar usa uma abordagem declarativa. Em vez de configurar tudo em JavaScript, defina 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>.

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 a pesquisa por proximidade.

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

Para fazer uma pesquisa inicial e mostrar 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 nesta etapa:

imagem

O elemento de pesquisa de lugar permite duas opções de pesquisa:

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 de interface para que eles selecionem um Tipo de lugar. Escolha o método de seleção mais adequado 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 há perto de um hotel, poderá escolher: bakery, coffee_shop, museum, restaurant e tourist_attraction.

Seu 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 elemento <gmp-place-nearby-search-request>, o 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 o 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 proximidade, você aninha um elemento <gmp-place-text-search-request>.

<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 à sua 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 elemento <gmp-place-text-search-request> 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 diz à API para preferir resultados dentro dessa á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 fazer uma pesquisa de lugar e preencher o elemento. Na próxima etapa, vamos melhorar a funcionalidade dele:

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

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

Primeiro, adicione uma variável global ao seu código JavaScript para armazenar os marcadores de lugar. Isso permite remover os elementos quando a pesquisa muda e processar eventos de clique.

let markers = {};

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

  • Remova todos os marcadores de lugar do mapa.
  • Faça um loop nos resultados do elemento de pesquisa de lugar e adicione um marcador para cada um.
  • Ajuste 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 listener de eventos gmp-load ao elemento <gmp-place-search>. Esse evento é acionado depois que uma pesquisa é concluída e os resultados são renderizados.

Vamos adicionar o listener à função de pesquisa (por exemplo, updatePlaceList) e use a opção { once: true } para garantir que ela seja acionada 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 fica 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 terá a seguinte aparência, com a capacidade de mostrar marcadores para cada lugar retornado pelo elemento de pesquisa de lugar:

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 de detalhes do lugar. Neste exemplo, vamos usar o Elemento compacto de detalhes do lugar.

Adicione o HTML do elemento compacto de detalhes do lugar 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 e só vai aparecer quando for 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 compacto de detalhes do lugar.

Crie uma variável global em JavaScript para manter uma referência ao elemento compacto de detalhes do lugar e preencha isso no seu código de inicialização. Por exemplo:

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

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

Depois disso, uma janela de informações será aberta para mostrar o elemento compacto de detalhes do lugar, 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 da lista de lugares e mostre o elemento compacto de detalhes do lugar, 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 Pesquisa por proximidade ou uma Pesquisa de texto para preencher o elemento da lista de lugares. Os resultados mostram alfinetes no mapa. Ao clicar em um alfinete ou em um lugar no elemento "Lista de lugares", uma janela de informações com detalhes do lugar é exibida, fornecida pelo elemento "Detalhes do lugar compacto".

O aplicativo vai ficar assim:

imagem

Conclusão

O elemento de pesquisa de lugar combinado com o elemento compacto de detalhes do lugar oferece uma maneira simplificada de adicionar recursos avançados de descoberta de lugares aos seus aplicativos da Plataforma Google Maps.

Experimente o Kit de Interface do Places hoje mesmo para permitir que seus usuários encontrem e explorem lugares usando pesquisas por texto e por proximidade, além de mostrar detalhes avançados, melhorando a interação com seus casos de uso de descoberta de lugares.

Colaboradores

Henrik Valve | Engenheiro de DevX