目标
了解如何将地点搜索元素与 Google 地图集成,以帮助用户使用附近搜索或文本搜索功能查找地点,从而增强他们探索地图注点的能力。使用地点详情紧凑型元素可提供有关应用中显示的地点的更多详细信息。
什么是地点搜索元素?
地点搜索元素是 Maps JavaScript API 中 Places UI Kit 的一部分。它是一个 HTML 元素,用于直接在应用中以列表格式呈现地点搜索结果。此元素可简化显示使用附近搜索或文本搜索功能找到的地点的流程,从而为用户提供顺畅的地点发现体验。当用户从列表中选择某个地点时,您可以在地图上显示该地点的详细信息,通常使用信息窗口和地点详情元素。
直观呈现地点发现情况
下图展示了 Place Search 元素的实际运作情形示例。左侧会显示餐厅列表(地点搜索元素)。选择餐厅后,地图上的信息窗口中会显示其详细信息,并且地图会以该餐厅的位置为中心。
地点发现功能的使用场景
集成地点搜索元素可以增强不同行业的各种应用:
- 旅游和观光:让游客能够搜索某个区域的景点、酒店或特定类型的菜肴。
- 房地产:让潜在买家或租客能够找到附近的学校、超市或公共交通选项。
- 物流和服务:帮助驾驶员查找电动汽车充电站、加油站或特定服务中心。
解决方案工作流:实现地点发现
本部分将逐步介绍如何集成地点搜索元素以在地图上发现地点,包括用于与 Places UI Kit 互动的代码段。我们将介绍如何初始化地图,以及如何实现附近搜索和文本搜索功能。最后,我们将使用 Place Details 元素在用户点击地图上的某个图钉时显示有关相应地点的更多详细信息。
前提条件
建议您熟悉以下文档:
- 地点搜索元素 - 用于通过附近搜索或文本搜索公开地点
- 地点详情元素 - 用于显示单个地点的详情
- Maps JavaScript API - 用于在网页上显示地图,以及导入 Places 界面套件
在您的项目中启用 Maps JavaScript API 和 Places 界面套件。
在开始之前,请验证您是否已加载 Maps JavaScript API 并导入所需的库。本文档还假定您具备 Web 开发方面的工作知识,包括 HTML、CSS 和 JavaScript。
向网页添加地图
第一步是将地图添加到网页中。此地图将用于以可选择的图钉形式显示地点搜索元素结果。
您可以通过两种方式向网页添加地图:
- 使用
gmp-map
HTML 网络组件。 - 使用 JavaScript。
本页上的代码段是使用 JavaScript 地图生成的。
地图可以以您希望用户搜索的某个位置(例如酒店)为中心,也可以初始化为请求用户当前位置以居中显示地图。在本文档中,我们将使用固定位置来锚定搜索。
如果您要直观呈现固定位置(例如酒店)附近的地点,请在地图上放置标记来表示此地点。例如:
地图以旧金山为中心,并显示一个蓝色图钉,表示我们正在搜索附近的地点。使用 PinElement
自定义了图钉颜色。
地图类型控件已从界面中隐藏。
设置地点搜索元素
现在,我们可以设置 HTML 和 CSS 来显示地点搜索元素。在此示例中,我们将元素浮动在地图的左侧,但建议您尝试不同的布局,以适合您的应用。
地点搜索元素采用声明式方法。您无需完全在 JavaScript 中配置,只需将请求元素(例如 <gmp-place-nearby-search-request>
)嵌套在主 <gmp-place-search>
组件中,即可直接在 HTML 中定义搜索类型。
在 HTML 代码中,初始化 <gmp-place-search>
元素。使用 selectable
属性可针对结果启用点击事件。在其中,添加一个 <gmp-place-nearby-search-request>
以指定此元素将用于附近搜索。
<gmp-place-search selectable>
<gmp-place-nearby-search-request>
</gmp-place-nearby-search-request>
</gmp-place-search>
为了执行初始搜索并显示结果,我们将使用 JavaScript 获取对嵌套请求元素的引用并设置其属性。初始化一个圆圈以用作 locationRestriction
,使用上一步中的标记位置作为中心点。然后,在请求元素上设置 locationRestriction
和 includedPrimaryTypes
属性以触发搜索。
相应的代码段如下所示:
// 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'];
应用在此阶段可能呈现的效果如下所示:
允许用户进行搜索
地点搜索元素支持两种搜索选项:
<gmp-place-nearby-search-request>
- 使用地点类型呈现地点附近搜索的搜索结果。<gmp-place-text-search-request>
- 使用自由文本输入(例如“旧金山的寿司”)呈现 Places Text Search 的搜索结果。
这些是 <gmp-place-search>
内的嵌套元素。然后,您可以使用 JavaScript 通过设置该嵌套请求元素上的属性来触发搜索。
本部分介绍了如何实现这两种方法。
附近搜索
如需允许用户执行附近搜索,您首先需要提供一个界面元素,供用户选择地点类型。选择最适合您应用的选择方法,例如填充了地点类型选择的下拉列表。
建议选择与您的使用情形相关的类型子集。
例如,如果您正在开发一款应用,用于向游客展示酒店附近的景点,则可以选择:bakery
、coffee_shop
、museum
、restaurant
和 tourist_attraction
。
您的 HTML 应包含 <gmp-place-search>
元素,其中嵌套了 <gmp-place-nearby-search-request>
。
<gmp-place-search selectable>
<gmp-place-nearby-search-request>
</gmp-place-nearby-search-request>
</gmp-place-search>
接下来,在地点类型选择器上为 change
事件创建 JavaScript 监听器。此监听器将调用一个用于更新 <gmp-place-nearby-search-request>
元素属性的函数,该函数会自动触发新的搜索并更新列表。
// 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];
}
设置步骤中的同一 searchCircle
用于 locationRestriction
。includedPrimaryTypes
属性设置为用户选择的值。此外,还可以设置可选的 maxResultCount
来限制结果数量。
文本搜索
如需启用文本搜索,您必须更改 HTML 配置。您将嵌套一个 <gmp-place-text-search-request>
元素,而不是附近的搜索请求。
<gmp-place-search selectable>
<gmp-place-text-search-request>
</gmp-place-text-search-request>
</gmp-place-search>
向界面添加文本输入和搜索按钮。为按钮的 click
事件创建 JavaScript 监听器。事件处理程序将获取用户输入,并更新 <gmp-place-text-search-request>
元素的属性以执行搜索。
// 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;
}
在此示例中,我们使用用户输入设置 textQuery
属性。我们还提供了一个使用当前地图边界的 locationBias
,该参数会告知 API 优先返回该区域内的结果,但不会严格限制结果必须位于该区域内。可选的 maxResultCount
可限制返回的结果数。
显示地点图钉和详情
现在,应用可以执行地点搜索并填充元素。在下一步中,我们将通过以下方式增强其功能:
- 在地图上为“地点搜索”元素中填充的每个地点显示图钉。
- 允许用户点击地点搜索元素中的图钉或地点,以显示有关该特定地点的更多详细信息。
无论应用是使用附近搜索还是文本搜索,此步骤的原理都是相同的。
首先,向 JavaScript 代码添加一个全局变量,用于存储地点标记。 这样,您就可以在搜索发生变化时移除这些元素,并处理点击事件。
let markers = {};
创建一个用于向地图添加标记的函数。每当加载新的搜索结果时,系统都会调用此函数。它将:
- 从地图中移除所有现有的地点标记。
- 循环遍历 Place Search Element 中的结果,并为每个结果添加一个标记。
- 调整地图的边界,以便所有新标记都可见。
如需监听搜索结果何时可用,请向 <gmp-place-search>
元素添加 gmp-load
事件监听器。此事件会在搜索完成且结果呈现后触发。
我们将在搜索函数(例如 updatePlaceList
),并使用 { once: true }
选项确保它仅针对当前搜索的结果触发。
// In your search function, after setting the request properties:
placeSearchElement.addEventListener('gmp-load', addMarkers, { once: true });
addMarkers
函数如下所示:
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);
}
}
完成此步骤后,应用将如下所示,能够显示地点搜索元素返回的每个地点的标记:
现在,我们已在地图上添加了标记,最后一步是处理标记和元素点击事件,以显示由地点详情元素提供的包含地点详情的信息窗口。在此示例中,我们将使用地点详情紧凑元素。
将地点详情精简元素 HTML 添加到您的代码中,例如:
<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
已设置为 display: none
;在需要之前,它不会显示。
gmp-place-all-content
会传递给渲染所有元素内容。如需选择要呈现的内容,请参阅地点详情紧凑元素文档。
在 JavaScript 中创建一个全局变量来保存对 Place Details Compact Element 的引用,并在初始化代码中填充此变量,例如:
let placeDetailsElement;
...
placeDetailsElement = document.querySelector('gmp-place-details-compact');
在 addMarkers
函数中,为每个标记添加 gmp-click
事件监听器,并通过传递当前标记的地点 ID 来配置地点详情紧凑元素以显示地点详情。
完成后,系统会打开一个信息窗口,以显示锚定在标记上的“地点详情”紧凑元素。
最后,地图会定位到所选地点的视口,使其可见。
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 });
});
});
...
});
}
}
如需让用户能够点击地点列表元素中的地点来显示地点详情紧凑元素,请在调用 configureFromSearchNearbyRequest
后将以下内容添加到 JavaScript 代码中。
placeSearchElement.addEventListener("gmp-select", ({ place }) => {
if (markers[place.id]) {
markers[place.id].click();
}
});
完成此步骤后,应用将能够使用附近搜索或文本搜索来填充地点列表元素。此操作的结果会在地图上显示图钉,点击图钉或地点列表元素中的地点会显示一个信息窗口,其中包含地点详情紧凑型元素提供的地点详情。
应用将如下所示:
总结
地点搜索元素与地点详情紧凑元素相结合,可为您的 Google Maps Platform 应用提供一种简化的方式来添加丰富的地点发现功能。
立即试用 Places UI Kit,让用户能够通过附近搜索和文本搜索来查找和探索地点,并显示丰富的地点详情,从而增强用户与地点发现用例的互动。
贡献者
Henrik Valve | DevX 工程师