Descoberta de lugares com PlaceSearchElement

Objetivo

Saiba como integrar o PlaceSearchElement ao Google Maps para ajudar os usuários a encontrar lugares usando a Pesquisa de Lugares Próximos ou a Pesquisa de Texto, melhorando a capacidade 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 é PlaceSearchElement?

O PlaceSearchElement faz parte do Kit de Interface do Places na API Maps JavaScript. É um elemento HTML que renderiza os resultados de um Place Search diretamente em um formato de lista no seu aplicativo. Esse elemento simplifica o processo de exibição de lugares encontrados usando uma Nearby Search ou uma Text Search, proporcionando uma experiência de usuário integrada para 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 Place Details.

Visualizar a descoberta de lugares

A imagem abaixo mostra um exemplo do PlaceSearchElement em ação. À esquerda, uma lista de restaurantes é exibida (o PlaceSearchElement). 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 PlaceSearchElement 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.
  • Imobiliário: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: como implementar a descoberta de lugares

Nesta seção, mostramos como integrar o PlaceSearchElement para descobrir lugares em um mapa, incluindo snippets de código para interagir com o Kit de Interface do Places. Saiba como inicializar o mapa e implementar a Nearby Search e a Text Search. Por fim, use o elemento Place Details para mostrar mais detalhes sobre um lugar quando um usuário clicar no pin 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 à sua página. Esse mapa será usado para mostrar os resultados de PlaceSearchElement como pins 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 a localização atual do usuário e 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 pesquisando nas proximidades. A cor do alfinete foi personalizada usando PinElement. O controle de tipo de mapa foi ocultado da interface.

Configurar PlaceSearchElement

Agora, configure o HTML e o CSS para exibir o PlaceSearchElement. Neste exemplo, o elemento flutua sobre o lado esquerdo do mapa, mas você pode testar layouts diferentes para se adequar ao seu aplicativo.

O PlaceSearchElement usa uma abordagem declarativa. Em vez de configurá-lo inteiramente 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 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 o JavaScript para receber uma referência ao elemento de solicitação aninhado e definir as propriedades dele. Inicialize um Circle 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 PlaceSearchElement 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.

Nesta seção, descrevemos como implementar os dois métodos.

imagem

Para permitir que os usuários façam uma Nearby Search, primeiro você precisa de um elemento da 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 lugar.

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.

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

<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 o Text Search, é necessário mudar a configuração do HTML. Em vez da solicitação de Nearby Search, 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 à 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;
}

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

Mostrar alfinetes e detalhes de lugares

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

  • Exibir pins no mapa para cada lugar preenchido no PlaceSearchElement.
  • Permitir que um usuário clique em um alfinete ou no lugar dentro do PlaceSearchElement para mostrar mais detalhes sobre esse lugar específico.

O princípio desta etapa é o mesmo, seja para uma Nearby Search ou para uma Text Search.

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 da pesquisa forem carregados. Ele vai:

  • Remova todos os marcadores de lugar do mapa.
  • Percorra os resultados do PlaceSearchElement 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 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 se parece com o exemplo abaixo:

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 de concluir essa etapa, o aplicativo vai ficar assim, com a capacidade de mostrar marcadores para cada lugar retornado pelo PlaceSearchElement:

imagem

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

Adicione o HTML do elemento compacto Place Details 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 só vai ficar visível 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 Place Details.

Crie uma variável global em JavaScript para manter uma referência ao elemento compacto de Place Details 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 compacto de Place Details para mostrar os detalhes do lugar transmitindo o ID de lugar do marcador atual.

Depois disso, uma janela de informações é aberta para mostrar o elemento compacto de Place Details, 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 de 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.

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 de lista de lugares. Os resultados vão mostrar alfinetes no mapa. Ao clicar em um alfinete ou em um lugar no elemento de lista de lugares, uma janela de informações com detalhes do lugar será exibida, fornecida pelo elemento compacto de Place Details.

O aplicativo vai ficar assim:

imagem

Conclusão

O PlaceSearchElement combinado com o elemento compacto do Place Details 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 que os usuários encontrem e explorem lugares usando pesquisas de texto e por perto, além de exibir detalhes avançados do lugar, melhorando a interação com seus casos de uso de descoberta de lugares.

Colaboradores

Henrik Valve | Engenheiro de DevX