Descubre lugares con el elemento Place Search y la API de Maps JavaScript

Objetivo

Aprende a integrar el elemento Place Search con Google Maps para ayudar a los usuarios a encontrar lugares con la búsqueda cercana o de texto, lo que mejora su capacidad de explorar puntos de interés. Usa el elemento Place Details Compact para proporcionar más detalles sobre los lugares que aparecen en tu aplicación.

¿Qué es el elemento Place Search?

El elemento Place Search forma parte del kit de IU de Places en la API de Maps JavaScript. Es un elemento HTML que renderiza los resultados de una búsqueda de lugares directamente en formato de lista dentro de tu aplicación. Este elemento simplifica el proceso de mostrar lugares encontrados con una búsqueda cercana o de texto, lo que proporciona una experiencia del usuario fluida para el descubrimiento de lugares. Cuando un usuario selecciona un lugar de la lista, puedes mostrar sus detalles en el mapa, a menudo con una ventana de información y el elemento Place Details.

Visualiza el descubrimiento de lugares

En la siguiente imagen, se muestra un ejemplo del elemento Place Search en acción. A la izquierda, se muestra una lista de restaurantes (el elemento Place Search). Cuando se selecciona un restaurante, sus detalles aparecen en una ventana de información en el mapa, y el mapa se centra en su ubicación.

imagen

Casos de uso para el descubrimiento de lugares

La integración del elemento Place Search puede mejorar varias aplicaciones en diferentes industrias:

  • Viajes y turismo: Permite que los turistas busquen atracciones, hoteles o tipos específicos de cocina en un área.
  • Bienes raíces: Permite que los compradores o inquilinos potenciales encuentren escuelas, supermercados o opciones de transporte público cercanos.
  • Logística y servicios: Ayuda a los conductores a encontrar estaciones de carga de VE, estaciones de servicio o centros de servicio específicos.

Flujo de trabajo de la solución: Implementación del descubrimiento de lugares

En esta sección, se explican los pasos para integrar el elemento Place Search para descubrir lugares en un mapa, incluidos fragmentos de código para interactuar con el kit de IU de Places. Abordaremos la inicialización del mapa y la implementación de las funcionalidades de búsqueda cercana y de texto. Por último, usaremos el elemento Place Details para mostrar más detalles sobre un lugar en particular cuando se haga clic en su pin en el mapa.

Requisitos previos

Se recomienda familiarizarse con la siguiente documentación:

Habilita la API de Maps JavaScript y el kit de IU de Places UI en tu proyecto.

Verifica que hayas cargado la API de Maps JavaScript y que hayas importado las bibliotecas necesarias antes de comenzar. En este documento, también se supone que tienes conocimientos prácticos sobre el desarrollo web, incluidos HTML, CSS y JavaScript.

Agrega un mapa a la página

El primer paso es agregar un mapa a tu página. Este mapa se usará para mostrar los resultados del elemento Place Search como pins seleccionables.

Existen dos formas de agregar un mapa a una página:

  1. Con un componente web HTML gmp-map HTML web component
  2. Con JavaScript

Los fragmentos de código de esta página se generaron con un mapa de JavaScript.

El mapa se puede centrar en una ubicación en la que deseas que el usuario busque, como un hotel, o inicializar para solicitar la ubicación actual del usuario para centrar el mapa. Para los fines de este documento, usaremos una ubicación fija para anclar la búsqueda.

Si visualizas lugares cercanos a una ubicación fija, como un hotel, coloca un marcador en el mapa para representar este lugar. Por ejemplo:

imagen

El mapa está centrado en San Francisco, con un pin azul para representar el lugar que buscamos cerca. El color del pin se personalizó con PinElement. El control Tipo de mapa se ocultó de la IU.

Configura el elemento Place Search

Ahora, podemos configurar el código HTML y CSS para mostrar el elemento Place Search. En este ejemplo, flotaremos el elemento sobre el lado izquierdo del mapa, pero te recomendamos que pruebes diferentes diseños para que se adapten a tu aplicación.

El elemento Place Search usa un enfoque declarativo. En lugar de configurarlo por completo en JavaScript, defines el tipo de búsqueda directamente en tu código HTML anidando un elemento de solicitud, como <gmp-place-nearby-search-request>, dentro del componente <gmp-place-search> principal.

Dentro de tu código HTML, inicializa un elemento <gmp-place-search>. Usa el atributo selectable para habilitar los eventos de clic en los resultados. Dentro de él, agrega un <gmp-place-nearby-search-request> para especificar que este elemento se usará para la búsqueda cercana.

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

Para realizar una búsqueda inicial y mostrar los resultados, usaremos JavaScript para obtener una referencia al elemento de solicitud anidado y establecer sus propiedades. Inicializa un círculo para usarlo como locationRestriction, con la posición del marcador del paso anterior como punto central. Luego, establece las propiedades locationRestriction y includedPrimaryTypes en el elemento de solicitud para activar la búsqueda.

El fragmento de código para esto es el siguiente:

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

A continuación, se muestra un ejemplo de cómo podría verse la aplicación en esta etapa:

imagen

El elemento Place Search permite dos opciones de búsqueda:

Estos son elementos anidados dentro de <gmp-place-search>. Luego, activas las búsquedas estableciendo propiedades en ese elemento de solicitud anidado con JavaScript.

En esta sección, se describe la implementación de ambos métodos.

imagen

Para permitir que los usuarios realicen una búsqueda cercana, primero necesitas un elemento de IU para que seleccionen un tipo de lugar. Elige el método de selección que mejor se adapte a tu aplicación, por ejemplo, una lista desplegable con una selección de tipos de lugares.

Te recomendamos que elijas un subconjunto de tipos que sean relevantes para tu caso de uso. Por ejemplo, si desarrollas una aplicación para mostrar a los turistas lo que hay cerca de un hotel, puedes elegir: bakery, coffee_shop, museum, restaurant y tourist_attraction.

Tu código HTML debe contener el elemento <gmp-place-search> con un <gmp-place-nearby-search-request> anidado en su interior.

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

A continuación, crea un objeto de escucha de JavaScript para el evento change en tu selector de tipo de lugar. Este objeto de escucha llamará a una función que actualiza las propiedades del <gmp-place-nearby-search-request> elemento, que activa automáticamente una nueva búsqueda y actualiza la 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];
}

El mismo searchCircle del paso de configuración se usa para locationRestriction. La propiedad includedPrimaryTypes se establece en el valor de la selección del usuario. También se establece un maxResultCount opcional para limitar la cantidad de resultados.

imagen

Para habilitar la búsqueda de texto, la configuración de HTML debe cambiar. En lugar de la solicitud de búsqueda cercana, anidas un elemento <gmp-place-text-search-request>.

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

Agrega una entrada de texto y un botón de búsqueda a tu IU. Crea un objeto de escucha de JavaScript para el evento click del botón. El controlador de eventos tomará la entrada del usuario y actualizará las propiedades del elemento <gmp-place-text-search-request> para realizar la búsqueda.

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

Aquí, establecemos la propiedad textQuery con la entrada del usuario. También proporcionamos un locationBias con los límites actuales del mapa, que le indica a la API que prefiera los resultados dentro de esa área sin restringirlos estrictamente. Un maxResultCount opcional limita la cantidad de resultados que se muestran.

Muestra los pins y los detalles de los lugares

Ahora, la aplicación puede realizar una búsqueda de lugares y propagar el elemento. En el siguiente paso, mejoraremos su funcionalidad de la siguiente manera:

  • Mostrar pins en el mapa para cada lugar propagado en el elemento Place Search
  • Permitir que un usuario haga clic en un pin o en el lugar dentro del elemento Place Search para mostrar más detalles sobre ese lugar en particular

El principio de este paso es el mismo, ya sea que la aplicación use una búsqueda cercana o de texto.

Primero, agrega una variable global a tu código JavaScript para almacenar los marcadores de lugar. Esto te permitirá quitarlos cuando cambie la búsqueda y controlar los eventos de clic.

let markers = {};

Crea una función para agregar marcadores al mapa. Se llamará a esta función cada vez que se carguen nuevos resultados de la búsqueda. Hará lo siguiente:

  • Quitará los marcadores de lugar existentes del mapa.
  • Recorrerá los resultados del elemento Place Search y agregará un marcador para cada uno.
  • Ajustará los límites del mapa para que sean visibles todos los marcadores nuevos.

Para escuchar cuando estén disponibles los resultados de la búsqueda, agrega un objeto de escucha de eventos gmp-load al elemento <gmp-place-search>. Este evento se activa después de que se completa una búsqueda y se renderizan los resultados.

Agregaremos el objeto de escucha dentro de nuestra función de búsqueda (p.ej., updatePlaceList) y usaremos la opción { once: true } para asegurarnos de que solo se active para los resultados de la búsqueda actual.

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

La función addMarkers se ve de la siguiente manera:

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 vez que se complete este paso, la aplicación se verá de la siguiente manera, con la capacidad de mostrar marcadores para cada lugar que muestra el elemento Place Search:

imagen

Ahora que tenemos marcadores en el mapa, el último paso es controlar los eventos de clic en el marcador y el elemento para mostrar una ventana de información con los detalles del lugar, que proporciona el elemento Place Details. En este ejemplo, usaremos el elemento Place Details Compact.

Agrega el código HTML del elemento Place Details Compact a tu código, por ejemplo:

<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 se establece en display: none; no será visible hasta que sea necesario. gmp-place-all-content se pasa para renderizar todo el contenido del elemento. Para elegir qué contenido renderizar, consulta la documentación del elemento Place Details Compact.

Crea una variable global en JavaScript para contener una referencia al elemento Place Details Compact y propágala en tu código de inicialización, por ejemplo:

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

Dentro de la función addMarkers, agrega un objeto de escucha de eventos gmp-click a cada marcador y configura el elemento Place Details Compact para mostrar los detalles del lugar pasando el ID de lugar del marcador actual.

Una vez que se complete esta acción, se abrirá una ventana de información para mostrar el elemento Place Details Compact, anclado en el marcador.

Por último, el mapa se posiciona en el viewport del lugar seleccionado, lo que lo hace visible.

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 el usuario haga clic en un lugar del elemento Place List para mostrar el elemento Place Details Compact, agrega lo siguiente al código JavaScript después de la llamada a configureFromSearchNearbyRequest.

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

Una vez que se complete este paso, la aplicación podrá usar una búsqueda cercana o de texto para propagar el elemento Place List. Los resultados de esto mostrarán pins en el mapa, y si haces clic en un pin o en un lugar del elemento Place List, se mostrará una ventana de información con los detalles del lugar, que proporciona el elemento Place Details Compact.

La aplicación se verá de la siguiente manera:

imagen

Conclusión

El elemento Place Search combinado con el elemento Place Details Compact proporciona una forma optimizada de agregar funciones de descubrimiento de lugares enriquecidas a tus aplicaciones de Google Maps Platform.

Prueba el kit de IU de Places hoy mismo para permitir que tus usuarios encuentren y exploren lugares con búsquedas cercanas y de texto, y muestren detalles enriquecidos de los lugares, lo que mejora su interacción con tus casos de uso de descubrimiento de lugares.

Colaboradores

Henrik Valve | DevX Ingeniero