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

Objetivo

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

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 app. Esse elemento simplifica o processo de exibição de lugares encontrados usando uma pesquisa por proximidade ou uma pesquisa 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 do Place Discovery

A integração do elemento de pesquisa de lugares 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 inquilinos 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ços específicos.

Fluxo de trabalho da solução: como implementar o Place Discovery

Esta seção orienta você nas 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 de pesquisa de texto. Por fim, vamos usar o elemento PlaceDetails para mostrar mais detalhes sobre um lugar específico ao clicar no alfinete dele no mapa.

Pré-requisitos

Recomendamos que você conheça a documentação a seguir:

Ative a API Maps JavaScript e o Kit de interface do usuário 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 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 de pesquisa de lugar como alfinetes selecionáveis.

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

  1. Usar 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 em que você quer que o usuário pesquise, como um hotel, ou inicializado para solicitar o local atual do usuário para centralizar o mapa. Para os 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. Exemplo:

imagem

O mapa está centralizado em São Francisco, com um alfinete azul para representar o lugar que estamos procurando nas proximidades. A cor do alfinete 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. Neste exemplo, vamos flutuar o elemento sobre o lado esquerdo do mapa, mas é recomendável tentar layouts diferentes para se adequar ao seu aplicativo.

No código HTML, crie um div que vai conter o elemento de pesquisa de lugar. Dentro disso, inicialize uma gmp-place-list vazia. Use o atributo selectable com gmp-place-list to para ativar eventos de clique no elemento.

<gmp-place-list selectable></gmp-place-list>

Nesse estágio, use configureFromSearchNearbyRequest para pesquisar um tipo de lugar e testar se os resultados estão sendo mostrados corretamente.

Use o JavaScript para configurar o elemento de pesquisa de lugar para mostrar os resultados de uma pesquisa de lugar. Inicialize um círculo para usar como locationRestriction, usando um ponto central e um raio adequado. Neste exemplo, o elemento é configurado para pesquisar um tipo de lugar restaurant, e a posição do marcador configurada na etapa anterior é usada como o ponto central do círculo.

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

const placeListElement = document.querySelector("gmp-place-list");
    const circleRestriction = new Circle({
        center: marker.position,
        radius: 500
    });
    placeListElement.configureFromSearchNearbyRequest({
        locationRestriction: circleRestriction,
        includedPrimaryTypes: ['restaurant'],
    });

Um exemplo de como o aplicativo pode ficar nesta fase é o seguinte:

imagem

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

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

imagem

Implemente um elemento da interface para permitir que o usuário escolha qual tipo de lugar o elemento de pesquisa de lugar vai mostrar. É recomendável escolher um subconjunto desses tipos para se adequar ao seu caso de uso. Por exemplo, se você estiver desenvolvendo um aplicativo para mostrar aos turistas o que há perto de um hotel, escolha: bakery, coffee_shop, museum, restaurant e tourist_attraction. Escolha o método de seleção que funcione melhor para seu app, por exemplo, uma lista suspensa preenchida com uma seleção de tipos de lugar.

Crie um listener JavaScript para processar o evento de mudança na interface de seleção de tipo de lugar. Configure o listener para chamar uma função e atualizar o elemento de pesquisa de lugar com base no tipo de lugar selecionado usando configureFromSearchNearbyRequest.

Confira um exemplo de atualização do elemento de pesquisa de lugar usando uma função:

// Function to update the place search
function updatePlaceList() {
    const selectedType = placeTypeSelect.value;
    if (!selectedType) {
        console.warn("No place type selected.");
        // Clear results or handle as needed
        placeListElement.requestedResultTypes = [];
        return;
    }
    placeListElement.configureFromSearchNearbyRequest({
        locationRestriction: searchCircle,
        maxResultCount: 8,
        includedPrimaryTypes: [selectedType],
    });
}

O mesmo locationRestriction de círculo configurado na etapa anterior é usado. O parâmetro includedPrimaryTypes é definido com base no valor selecionado na interface. Um maxResultCount opcional também foi definido para restringir o número de resultados retornados e exibidos no elemento de pesquisa de lugar.

imagem

Adicione uma entrada de texto com um botão para que os usuários insiram a pesquisa de texto. Crie um listener de JavaScript para processar o evento click no botão e configure o elemento de pesquisa de lugar para pesquisar usando a string de pesquisa inserida, usando configureFromSearchByTextRequest.

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;
    }
        placeListElement.configureFromSearchByTextRequest({
            textQuery: query,
            locationRestriction: map.getBounds(),
            maxResultCount: 8,
        });
}

Neste exemplo, um locationRestriction opcional é definido usando os limites atuais do mapa. A consulta de pesquisa é transmitida usando o parâmetro textQuery. Um maxResultCount opcional também foi definido para restringir o número de resultados retornados e exibidos no elemento de pesquisa de lugar.

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:

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

O princípio desta etapa será o mesmo, esteja o aplicativo usando configureFromSearchNearbyRequest ou configureFromSearchByTextRequest. Para este exemplo, vamos usar configureFromSearchNearbyRequest.

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 para mostrar os detalhes do lugar.

let markers = {};

Adicione uma função a:

  • Remova os marcadores de lugar atuais.
  • Percorrer os resultados do elemento de pesquisa de lugar e adicionar um marcador para cada um.
  • Defina os limites do mapa para que todos os marcadores fiquem visíveis.
async function addMarkers() {
    const { LatLngBounds } = await google.maps.importLibrary("core");
    const bounds = new LatLngBounds();
    if (placeListElement.places.length > 0) {
        // Remove existing markers
        for (m in markers) {
            markers[m].map = null;
        }
        markers = {};
        // Loop through each place in the Place Search Element
        // Add a marker for each place
        placeListElement.places.forEach((place) => {
            let marker = new AdvancedMarkerElement({
                map: map,
                position: place.location,
            });
            markers[place.id] = marker;
            bounds.extend(place.location);
            marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;
            // Position the map to display all markers with the bounds
            map.setCenter(bounds.getCenter());
            map.fitBounds(bounds);
        });
    }
}

Por fim, quando a promessa configureFromSearchNearbyRequest for resolvida com sucesso, chame a nova função addMarkers(), como esta:

placeListElement.configureFromSearchNearbyRequest({
            locationRestriction: searchCircle,
            maxResultCount: 8,
            includedPrimaryTypes: [selectedType],
        }).then(addMarkers);

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

imagem

Agora que temos marcadores no mapa, a última etapa é processar os eventos de clique do marcador e do 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 não vai ficar visível até que seja 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 no JavaScript para armazenar uma referência ao elemento compacto de detalhes do lugar 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 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 lugar do marcador atual.

Depois disso, uma janela de informações é aberta para mostrar o elemento compacto de detalhes do lugar, ancorado no marcador.

Por fim, o mapa é posicionado na viewport 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 para mostrar o elemento compacto de detalhes do lugar, adicione o seguinte ao código JavaScript após a chamada para configureFromSearchNearbyRequest.

placeListElement.addEventListener("gmp-placeselect", ({ place }) => {
    markers[place.id].click();
});

Depois que essa etapa for concluída, o aplicativo poderá usar uma pesquisa por texto ou por proximidade para preencher o elemento da lista de lugares. Os resultados vão mostrar alfinetes no mapa, e clicar em um alfinete ou lugar no elemento da lista de lugares vai mostrar uma janela de informações com detalhes do lugar, fornecidos pelo elemento compacto de detalhes do lugar.

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.

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

Colaboradores

Henrik Valve | Engenheiro do DevX