目標
瞭解如何整合地點搜尋元素與 Google 地圖,協助使用者透過附近搜尋或文字搜尋功能尋找地點,提升探索景點的能力。使用 Place Details Compact 元素,提供應用程式中顯示地點的詳細資訊。
什麼是 Place Search 元素?
地點搜尋元素是 Maps JavaScript API 中 Places UI Kit 的一部分。這個 HTML 元素會直接在應用程式中,以清單格式顯示地點搜尋結果。這個元素可簡化顯示使用「附近搜尋」或「文字搜尋」找到的地點的程序,提供流暢的地點探索使用者體驗。使用者從清單中選取地點時,您可以在地圖上顯示詳細資料,通常會使用資訊視窗和 Place Details 元素。
以視覺化方式呈現地點探索
下圖顯示 Place Search 元素的實際運作情形。左側會顯示餐廳清單 (地點搜尋元素)。選取餐廳後,地圖上的資訊視窗會顯示餐廳詳細資料,地圖也會以餐廳位置為中心。
地點探索功能的使用案例
整合地點搜尋元素可提升各行各業的各種應用程式:
- 旅遊和觀光:讓遊客搜尋特定區域的景點、飯店或特定料理。
- 房地產:讓潛在買家或租屋者尋找附近的學校、超市或大眾運輸選項。
- 物流和服務:協助駕駛人尋找電動車充電站、加油站或特定服務中心。
解決方案工作流程:導入地點探索功能
本節將逐步說明如何整合地點搜尋元素,以便在地圖上探索地點,包括與 Places UI Kit 互動的程式碼片段。我們將說明如何初始化地圖,以及實作「附近搜尋」和「文字搜尋」功能。最後,我們會使用「地點詳細資料」元素,在使用者點選地圖上的圖釘時,顯示特定地點的詳細資料。
必要條件
建議您先熟悉下列說明文件:
- Place Search 元素 - 用於透過 Nearby Search 或 Text Search 顯示地點
- Place Details 元素 - 用於顯示個別地點的詳細資料
- Maps JavaScript API:用於在網頁上顯示地圖,以及匯入 Places UI Kit
在專案中啟用 Maps JavaScript API 和 Places UI Kit。
開始前,請確認您已載入 Maps JavaScript API,並匯入必要程式庫。本文也假設您具備網頁開發工作知識,包括 HTML、CSS 和 JavaScript。
在頁面中新增地圖
第一步是在網頁中加入地圖。這張地圖會以可選取的圖釘顯示地點搜尋元素結果。
在網頁中加入地圖的方式有兩種:
- 使用
gmp-map
HTML 網頁元件。 - 使用 JavaScript。
本頁的程式碼片段是使用 JavaScript 地圖產生。
地圖可以以使用者要搜尋的地點 (例如飯店) 為中心,也可以初始化為要求使用者提供目前位置,然後以該位置為中心。為方便說明,本文將使用固定位置做為搜尋錨點。
如果想顯示固定位置 (例如飯店) 附近的地點,請在地圖上放置標記來代表這個地點。例如:
地圖中心位於舊金山,藍色圖釘代表我們在附近搜尋的地點。圖釘顏色已使用 PinElement
自訂。「地圖類型」控制項已從使用者介面隱藏。
設定 Place Search 元素
現在,我們可以設定 HTML 和 CSS,顯示地點搜尋元素。在本範例中,我們將元素浮動至地圖左側,但建議您嘗試不同的版面配置,以符合應用程式需求。
地點搜尋元素採用宣告式方法。您不必完全在 JavaScript 中設定,只要在主要 <gmp-place-search>
元件內,將要求元素 (例如 <gmp-place-nearby-search-request>
) 巢狀化,即可直接在 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 取得巢狀要求元素的參照,並設定其屬性。初始化 Circle 做為 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>
:使用 Place Types,從 Places Nearby Search 算繪搜尋結果。<gmp-place-text-search-request>
- 使用「舊金山的壽司」等自由文字輸入內容,從地點文字搜尋算繪搜尋結果。
這些是 <gmp-place-search>
內的巢狀元素。然後使用 JavaScript 在該巢狀要求元素上設定屬性,觸發搜尋。
本節將說明如何實作這兩種方法。
鄰近搜尋
如要允許使用者執行附近搜尋,您必須先提供 UI 元素,供使用者選取地點類型。選擇最適合應用程式的選取方法,例如填入一系列地點類型的下拉式清單。
建議您選擇與用途相關的類型子集。
舉例來說,如果您要開發應用程式,向觀光客顯示飯店附近的景點,可以選擇: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];
}
locationRestriction
使用的 searchCircle
與設定步驟相同。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>
在 UI 中新增文字輸入內容和搜尋按鈕。為按鈕的 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 = {};
建立函式,在地圖中加入標記。每當載入新的搜尋結果時,系統就會呼叫這個函式。這項功能可:
- 從地圖中移除所有現有的地點標記。
- 逐一查看地點搜尋元素傳回的結果,並為每個結果新增標記。
- 調整地圖的邊界,確保所有新標記都顯示在地圖上。
如要監聽搜尋結果何時可用,請將 gmp-load
事件監聽器新增至 <gmp-place-search>
元素。搜尋完成並顯示結果後,系統會觸發這個事件。
我們會在搜尋函式中新增事件監聽器 (例如 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);
}
}
完成這個步驟後,應用程式會如下所示,並可顯示地點搜尋元素傳回的每個地點標記:
地圖上現在有標記,最後一個步驟是處理標記和元素點擊事件,顯示含有地點詳細資料的資訊視窗,這些資料由 Place Details Element 提供。在本範例中,我們將使用「Place Details Compact Element」。
在程式碼中加入地點詳細資料精簡元素 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 元素參照,並在初始化程式碼中填入此變數,例如:
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 地圖平台應用程式中新增豐富地點探索功能的方式。
立即試用 Places UI Kit,讓使用者透過附近地點搜尋和文字搜尋功能尋找及探索地點,並顯示豐富的地點詳細資料,提升使用者與地點探索應用情境的互動。
貢獻者
Henrik Valve | DevX 工程師