使用 Places 界面套件构建交互式商店查找工具

目标

本文档将详细介绍使用 Google Maps Platform(特别是 Maps JavaScript API 和 Places UI Kit:地点详情元素)开发交互式店铺查找器应用的关键步骤。您将学习如何创建显示实体店位置的地图、动态更新可见实体店的列表,以及显示每个实体店的丰富地点信息。

前提条件

建议您熟悉以下内容:

在您的项目中启用 Maps JavaScript APIPlaces 界面套件

在开始之前,请验证您是否已加载 Maps JavaScript API 并导入高级标记地点界面套件所需的库。本文档还假定您具备 Web 开发方面的工作知识,包括 HTML、CSS 和 JavaScript。

初始设置

第一步是将地图添加到网页中。此地图将用于显示与您的实体店位置相关的图钉。

您可以通过两种方式向网页添加地图:

  1. 使用 gmp-map HTML Web 组件
  2. 使用 JavaScript

选择最适合您的应用场景的方法。本指南适用于这两种实现地图的方式。

演示

此演示展示了实体店查询工具的实际使用情况,其中显示了湾区的 Google 办事处位置。系统会针对每个位置显示地点详情元素,以及一些示例属性。

加载和显示实体店位置

在本部分中,我们将加载您的商店数据并在地图上显示这些数据。本指南假设您拥有一个可从中提取现有商店信息的知识库。您的商店数据可以来自各种来源,例如您的数据库。 在此示例中,我们假设有一个本地 JSON 文件 (stores.json),其中包含一个商店对象数组,每个对象代表一个商店位置。每个对象都应至少包含 namelocation(包含 latlng)和 place_id

如果您还没有商店地点的地点 ID,可以通过多种方式检索这些 ID。如需了解详情,请参阅地点 ID 文档

stores.json 文件中的实体店详细信息条目示例如下所示。 包含名称、位置(纬度/经度)和地点 ID 字段。有一个对象用于保存商店营业时间(截断)。还有两个布尔值可用于描述商店位置的定制功能。

{
  "name": "Example Store Alpha",
  "location": { "lat": 51.51, "lng": -0.12 },
  "place_id": "YOUR_STORE_PLACE_ID",
  "opening_hours": { "Monday": "09:00 - 17:00", "...": "..." },
  "new_store_design": true,
  "indoor_seating": false
}

在 JavaScript 代码中,提取实体店位置的数据,并在地图上为每个实体店显示一个图钉。

以下示例展示了如何执行此操作。此函数会接受一个包含商店详细信息的对象,并根据每个商店的位置创建一个标记。

function displayInitialMarkers(storeLocations) {
    if (!AdvancedMarkerElement || !LatLng || !mapElement) return;
    storeLocations.forEach(store => {
        if (store.location) {
            const marker = new AdvancedMarkerElement({
                position: new LatLng(store.location.lat, store.location.lng),
                title: store.name
            });
            mapElement.appendChild(marker);
        }
    });
}

加载商店并让地图上显示代表其位置的图钉后,使用 HTML 和 CSS 创建一个侧边栏,以显示各个商店的详细信息。

在此阶段,您的实体店定位器可能如下所示:

图片

监听地图视口更改

为了优化性能和用户体验,请更新您的应用,使其仅在标记及其对应位置位于可见地图区域(视口)内时,才在边栏中显示这些标记和详细信息。这包括监听地图视口更改、对这些事件进行去抖动,然后仅重新绘制必要的标记。

将事件监听器附加到地图的空闲事件。此事件会在任何平移或缩放操作完成后触发,从而为您的计算提供稳定的视口。

map.addListener('idle', debounce(updateMarkersInView, 300));

上述代码段会监听 idle 事件,并调用 debounce 函数。使用防抖动功能可确保标记更新逻辑仅在用户停止与地图互动一小段时间后运行,从而提高性能。

function debounce(func, delay) {
    let timeoutId;
    return function(...args) {
        const context = this;
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            func.apply(context, args);
        }, delay);
    };
}

上述代码是一个去抖动函数示例。它接受一个函数和一个延迟实参,这两个实参可在空闲监听器中看到。300 毫秒的延迟足以等待地图停止移动,而不会给界面增加明显的延迟。 此超时时间到期后,系统会调用传递的函数,在本例中为 updateMarkersInView

updateMarkersInView 函数应执行以下操作:

清除地图上的所有现有标记

检查商店的位置是否位于当前地图边界内,例如:

if (map.getBounds().contains(storeLatLng)) {
  // logic
}

在上述 if 语句中,编写代码以在商店位置位于地图视口内时,在侧边栏上显示标记和商店详细信息。

使用地点详情元素显示丰富的地点详情

在此阶段,应用会显示所有实体店位置,用户可以根据地图视口过滤这些位置。为了增强此功能,我们使用地点详情元素添加了有关每家商店的丰富详细信息,例如照片、评价和无障碍设施信息。此示例专门使用了地点详情紧凑元素

数据源中的每个实体店位置都必须具有相应的地点 ID。此 ID 可唯一标识 Google 地图上的相应地点,对于提取该地点的详细信息至关重要。您通常会预先获取这些地点 ID,并将其存储在每个商店记录中。

在应用中集成“地点详情精简元素”

当系统确定某个商店位于当前地图视口内,并且正在边栏中渲染该商店时,您可以动态创建并插入该商店的“地点详情”紧凑型元素。

对于正在处理的当前商店,从您的数据中检索地点 ID。地点 ID 用于控制元素将显示在哪个地点。

在 JavaScript 中,动态创建 PlaceDetailsCompactElement 的实例。系统还会创建一个新的 PlaceDetailsPlaceRequestElement,并将地点 ID 传递给它,然后将其附加到 PlaceDetailsCompactElement。最后,使用 PlaceContentConfigElement 配置元素将显示的内容。

以下函数假定必要的 Place UI Kit 库已导入并可在调用此函数的范围内使用,并且传递给函数的 storeData 包含 place_id

此函数将返回元素,调用代码将负责将其附加到 DOM。

function createPlaceDetailsCompactElement(storeData) {
    // Create the main details component
    const detailsCompact = new PlaceDetailsCompactElement();
    detailsCompact.setAttribute('orientation', 'vertical'); // Or 'horizontal'

    // Specify the Place ID
    const placeRequest = new PlaceDetailsPlaceRequestElement();
    placeRequest.place = storeData.place_id;
    detailsCompact.appendChild(placeRequest);

    // Configure which content elements to display
    const contentConfig = new PlaceContentConfigElement();
    // For this example, we'll render media, rating, accessibility, and attribution:
    contentConfig.appendChild(new PlaceMediaElement({ lightboxPreferred: true }));
    contentConfig.appendChild(new PlaceRatingElement());
    contentConfig.appendChild(new PlaceAccessibleEntranceIconElement());
    // Configure attribution
    const placeAttribution = new PlaceAttributionElement();
    placeAttribution.setAttribute('light-scheme-color', 'gray');
    placeAttribution.setAttribute('dark-scheme-color', 'gray');
    contentConfig.appendChild(placeAttribution);
    detailsCompact.appendChild(contentConfig);
    // Return the element
    return detailsCompact;
}

在上面的示例代码中,该元素配置为显示地点照片、评价评分和无障碍信息。您可以通过添加或移除其他可用的内容元素来自定义此设置,如需了解所有可用的选项,请参阅 PlaceContentConfigElement 文档。

地点详情紧凑元素支持通过 CSS 自定义属性设置样式。这样,您就可以根据应用的设计量身定制其外观(颜色、字体等)。在 CSS 文件中应用这些自定义属性。如需了解受支持的 CSS 属性,请参阅 PlaceDetailsCompactElement 的参考文档。

以下示例展示了您的应用在此阶段可能呈现的效果:

图片

增强实体店查找器功能

您已为实体店查询应用打下坚实的基础。现在,我们来考虑几种扩展其功能的方法,以打造更丰富、更以用户为中心的体验。

添加自动补全

通过将搜索输入与地点自动补全功能集成,改进用户查找商店搜索区域的方式。当用户输入地址、社区或地图注点并选择建议时,将地图编程为自动以该位置为中心,从而触发附近商店的更新。为此,请添加一个输入字段,并将地点自动补全功能附加到该字段。选择建议后,地图可以以该点为中心。请务必将其配置为偏向或限制为您的运营区域。

检测位置

通过实现检测用户当前地理位置的功能,提供即时相关性,尤其对于移动设备用户而言。在获得浏览器权限以检测用户的位置后,自动将地图居中显示在用户的位置,并显示最近的商店。用户在寻找即时选项时,非常看重我附近功能。添加按钮或初始提示,以请求位置信息访问权限。

显示距离和路线

用户找到感兴趣的商店后,通过集成 Routes API 可显著改善其体验。针对您列出的每家商店,计算并显示其与用户当前位置或搜索位置之间的距离。此外,还应提供一个按钮或链接,用于使用 Routes API 生成从用户位置到所选商店的路线。然后,您可以在地图上显示此路线,也可以链接到 Google 地图以进行导航,从而实现从查找商店到实际前往商店的无缝过渡。

通过实现这些扩展服务,您可以利用 Google Maps 平台的更多功能来构建更全面、更便捷的商店定位器,直接满足用户的常见需求。

总结

本指南演示了构建互动式实体店查找器的核心步骤。您已了解如何使用 Maps JavaScript API 在地图上显示自己的实体店位置,如何根据视口变化动态更新显示的实体店,以及如何与 Places UI Kit 保持一致地显示自己的实体店数据。通过将现有实体店信息(包括地点 ID)与地点详情元素搭配使用,您可以为每个营业地点呈现丰富且标准化的详情,从而为打造用户友好的实体店定位工具奠定坚实的基础。

不妨试试 Maps JavaScript APIPlaces 界面套件,它们可提供强大的基于组件的工具,帮助您快速开发复杂的基于位置的应用。通过结合使用这些功能,您可以为用户打造富有吸引力且信息丰富的体验。

贡献者

Henrik Valve | DevX 工程师