使用 Places UI Kit 的店铺查找工具

目标

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

前提条件

建议您熟悉以下内容:

在项目中启用 Maps JavaScript API 和 Places UI Kit。

在开始之前,请验证您是否已加载 Maps JavaScript API,并导入了高级标记和 Places UI Kit 所需的库。本文档还假定您具备 Web 开发(包括 HTML、CSS 和 JavaScript)方面的实践知识。

初始设置

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

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

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

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

加载并显示商店位置

在本部分中,我们将在地图上加载并显示您的商店数据。本指南假定您有一个可从中提取现有商店信息的代码库。您的商店数据可以来自各种来源,例如您的数据库。 在此示例中,我们假设有一个本地 JSON 文件 (stores.json),其中包含一个商店对象数组,每个对象代表一个店面位置。每个对象应至少包含 name、location(包含 lat 和 lng)以及 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 创建一个边栏,以显示各个商店的详细信息。

以下示例展示了店铺定位工具在此阶段可能呈现的效果:

图片

监听地图视口更改

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

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

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 Platform 的更多功能来构建更全面、更便捷的店铺定位工具,直接满足常见的用户需求。

总结

本指南演示了构建互动式商店查找工具的核心步骤。 您已了解如何使用 Maps JavaScript API 在地图上显示自己的店面位置,如何根据视口变化动态更新可见商店,以及如何按照 Places UI Kit 的要求显示自己的商店数据。通过将现有商店信息(包括地点 ID)与地点详情元素结合使用,您可以为每个营业地点呈现丰富、标准化的详细信息,为打造人性化的店铺定位工具奠定坚实的基础。

试用 Maps JavaScript API 和 Places UI Kit,利用基于组件的强大工具快速开发复杂的地理定位应用。通过结合使用这些功能,您可以为用户打造引人入胜且信息丰富的体验。

贡献者

Henrik Valve | DevX 工程师