Place Autocomplete 小工具會建立文字輸入欄位、在 UI 選單中提供地點預測結果,以及傳回 Place Details 以回應使用者的選取項目。使用 Place Autocomplete 小工具,在網頁上嵌入完整的自動完成使用者介面。
必要條件
如要使用 Place Autocomplete (預先發布版),請務必在 Google Cloud 專案中啟用「Places API」,並在 Bootstrap 載入器中指定 Beta 版 (v: "beta"
)。詳情請參閱「開始使用」一文。
最新資訊
Place Autocomplete (預先發布版) 包含下列改善項目:
- Autocomplete 小工具 UI 支援區域本地化 (包括 RTL 語言),適用於文字輸入預留位置、預測結果清單標誌和地點預測結果。
- 進階無障礙功能,包括支援螢幕閱讀器和鍵盤互動。
- Autocomplete 小工具會傳回新的 Place 類別,簡化回傳物件的處理流程。
- 更有效地支援行動裝置和小螢幕。
- 更出色的效能,更清楚的圖形外觀。
新增 Autocomplete 小工具
您可以在網頁或 Google 地圖中加入 Autocomplete 小工具。Autocomplete 小工具會建立文字輸入欄位、在 UI 選單中提供地點預測結果,以及透過 gmp-placeselect
事件監聽器傳回 Place Details 以回應使用者點擊。本節將說明如何在網頁或 Google 地圖中加入 Autocomplete 小工具。
在網頁中加入 Autocomplete 小工具
如要在網頁中加入 Autocomplete 小工具,請建立新的 google.maps.places.PlaceAutocompleteElement
,然後附加至網頁,如以下範例所示:
TypeScript
// Request needed libraries. //@ts-ignore await google.maps.importLibrary("places") as google.maps.PlacesLibrary; // Create the input HTML element, and append it. //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore document.body.appendChild(placeAutocomplete);
JavaScript
// Request needed libraries. //@ts-ignore await google.maps.importLibrary("places"); // Create the input HTML element, and append it. //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore document.body.appendChild(placeAutocomplete);
在地圖中加入 Autocomplete 小工具
如要在地圖中加入 Autocomplete 小工具,請建立新的 google.maps.places.PlaceAutocompleteElement
例項,將 PlaceAutocompleteElement
附加至 div
,然後將其推送至地圖做為自訂控制項,如以下範例所示:
TypeScript
//@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = 'place-autocomplete-input'; const card = document.getElementById('place-autocomplete-card') as HTMLElement; //@ts-ignore card.appendChild(placeAutocomplete); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
JavaScript
//@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = "place-autocomplete-input"; const card = document.getElementById("place-autocomplete-card"); //@ts-ignore card.appendChild(placeAutocomplete); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
限制 Autocomplete 預測結果
根據預設,Place Autocomplete 會顯示所有地點類型 (優先顯示使用者所在位置附近的預測結果),並擷取使用者所選地點的所有可用資料欄位。您可以限制或自訂調整結果,將 PlaceAutocompleteElementOptions 設為顯示更相關的預測結果。
限制結果後,Autocomplete 小工具會略過超出限制區域的所有結果。常見做法是將結果限制在地圖範圍內。自訂調整結果會讓 Autocomplete 小工具顯示指定區域內的結果,但有些相符項目可能會超出這個區域。
如果您未提供任何邊界或地圖可視區域,API 就會嘗試根據使用者的 IP 位址偵測所在位置,然後針對該位置調整結果。請盡可能設定邊界,否則不同使用者可能會收到不同的預測結果。此外,為了改善整體預測結果,請務必提供合理的可視區域,例如您透過平移或縮放地圖設定的可視區域,或是開發人員根據裝置位置和半徑設定的可視區域。如果沒有設定半徑,系統會將 5 公里視為 Place Autocomplete 的合理預設值。請勿將可視區域設為下列值:半徑為零 (單一點)、範圍僅有幾公尺 (小於 100 公尺),或是橫跨全球。
按國家/地區限制 Place Search
如要將 Place Search 限制在一或多個特定國家/地區,請使用 componentRestrictions
屬性指定國家/地區代碼,如以下程式碼片段所示:
const pac = new google.maps.places.PlaceAutocompleteElement({ componentRestrictions: {country: ['us', 'au']}, });
將 Place Search 限制在地圖範圍內
如要將 Place Search 限制在地圖邊界內,請使用 locationRestrictions
屬性新增邊界,如以下程式碼片段所示:
const pac = new google.maps.places.PlaceAutocompleteElement({ locationRestriction: map.getBounds(), });
限制地圖範圍時,請務必新增事件監聽器,在範圍變更時加以更新:
map.addListener('bounds_changed', () => { autocomplete.locationRestriction = map.getBounds(); });
如要移除 locationRestriction
,請設為 null
。
自訂調整 Place Search 結果
使用 locationBias
屬性並傳遞半徑,將 Place Search 結果自訂調整為僅限某個圓形區域,如下所示:
const autocomplete = new google.maps.places.PlaceAutocompleteElement({ locationBias: {radius: 100, center: {lat: 50.064192, lng: -130.605469}}, });
如要移除 locationBias
,請設為 null
。
將 Place Search 結果限制為特定類型
使用 types
屬性並指定一或多個類型,將 Place Search 結果限制為特定類型的地點,如下所示:
const autocomplete = new google.maps.places.PlaceAutocompleteElement({ types: ['establishment'], });
如需支援類型的完整清單,請參閱「表 3:Place Autocomplete 要求支援的類型」。
取得 Place Details
如要取得所選地點的 Place Details,請在 PlaceAutocompleteElement
中加入 gmp-placeselect
事件監聽器,如以下範例所示:
TypeScript
// Add the gmp-placeselect listener, and display the results. //@ts-ignore placeAutocomplete.addEventListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); selectedPlaceTitle.textContent = 'Selected Place:'; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2); });
JavaScript
// Add the gmp-placeselect listener, and display the results. //@ts-ignore placeAutocomplete.addEventListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); selectedPlaceTitle.textContent = "Selected Place:"; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2, ); });
在上例中,事件監聽器會傳回 Place 類別的物件。呼叫 place.fetchFields()
即可取得應用程式所需的 Place Details 資料欄位。
下例中的事件監聽器會要求地點資訊,並將這項資訊顯示在地圖上。
TypeScript
// Add the gmp-placeselect listener, and display the results on the map. //@ts-ignore placeAutocomplete.addEventListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + '</span><br />' + '<span id="place-address">' + place.formattedAddress + '</span>' + '</div>'; updateInfoWindow(content, place.location); marker.position = place.location; });
JavaScript
// Add the gmp-placeselect listener, and display the results on the map. //@ts-ignore placeAutocomplete.addEventListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + "</span><br />" + '<span id="place-address">' + place.formattedAddress + "</span>" + "</div>"; updateInfoWindow(content, place.location); marker.position = place.location; });
地圖範例
本節包含本頁上地圖範例的完整程式碼。
Autocomplete 元素
本例會在網頁中加入 Autocomplete 小工具,並顯示各個所選地點的結果。
TypeScript
async function initMap(): Promise<void> { // Request needed libraries. //@ts-ignore await google.maps.importLibrary("places") as google.maps.PlacesLibrary; // Create the input HTML element, and append it. //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore document.body.appendChild(placeAutocomplete); // Inject HTML UI. const selectedPlaceTitle = document.createElement('p'); selectedPlaceTitle.textContent = ''; document.body.appendChild(selectedPlaceTitle); const selectedPlaceInfo = document.createElement('pre'); selectedPlaceInfo.textContent = ''; document.body.appendChild(selectedPlaceInfo); // Add the gmp-placeselect listener, and display the results. //@ts-ignore placeAutocomplete.addEventListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); selectedPlaceTitle.textContent = 'Selected Place:'; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. //@ts-ignore await google.maps.importLibrary("places"); // Create the input HTML element, and append it. //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore document.body.appendChild(placeAutocomplete); // Inject HTML UI. const selectedPlaceTitle = document.createElement("p"); selectedPlaceTitle.textContent = ""; document.body.appendChild(selectedPlaceTitle); const selectedPlaceInfo = document.createElement("pre"); selectedPlaceInfo.textContent = ""; document.body.appendChild(selectedPlaceInfo); // Add the gmp-placeselect listener, and display the results. //@ts-ignore placeAutocomplete.addEventListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); selectedPlaceTitle.textContent = "Selected Place:"; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2, ); }); } initMap();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } p { font-family: Roboto, sans-serif; font-weight: bold; }
HTML
<html> <head> <title>Place Autocomplete element</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <p style="font-family: roboto, sans-serif">Search for a place here:</p> <!-- prettier-ignore --> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "beta"});</script> </body> </html>
測試範例
自動完成地圖
本例顯示如何在 Google 地圖中加入 Autocomplete 小工具。
TypeScript
let map: google.maps.Map; let marker: google.maps.marker.AdvancedMarkerElement; let infoWindow: google.maps.InfoWindow; async function initMap(): Promise<void> { // Request needed libraries. //@ts-ignore const [{ Map }, { AdvancedMarkerElement }] = await Promise.all([ google.maps.importLibrary("marker"), google.maps.importLibrary("places") ]); // Initialize the map. map = new google.maps.Map(document.getElementById('map') as HTMLElement, { center: { lat: 40.749933, lng: -73.98633 }, zoom: 13, mapId: '4504f8b37365c3d0', mapTypeControl: false, }); //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = 'place-autocomplete-input'; const card = document.getElementById('place-autocomplete-card') as HTMLElement; //@ts-ignore card.appendChild(placeAutocomplete); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card); // Create the marker and infowindow marker = new google.maps.marker.AdvancedMarkerElement({ map, }); infoWindow = new google.maps.InfoWindow({}); // Add the gmp-placeselect listener, and display the results on the map. //@ts-ignore placeAutocomplete.addEventListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + '</span><br />' + '<span id="place-address">' + place.formattedAddress + '</span>' + '</div>'; updateInfoWindow(content, place.location); marker.position = place.location; }); } // Helper function to create an info window. function updateInfoWindow(content, center) { infoWindow.setContent(content); infoWindow.setPosition(center); infoWindow.open({ map, anchor: marker, shouldFocus: false, }); } initMap();
JavaScript
let map; let marker; let infoWindow; async function initMap() { // Request needed libraries. //@ts-ignore const [{ Map }, { AdvancedMarkerElement }] = await Promise.all([ google.maps.importLibrary("marker"), google.maps.importLibrary("places"), ]); // Initialize the map. map = new google.maps.Map(document.getElementById("map"), { center: { lat: 40.749933, lng: -73.98633 }, zoom: 13, mapId: "4504f8b37365c3d0", mapTypeControl: false, }); //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = "place-autocomplete-input"; const card = document.getElementById("place-autocomplete-card"); //@ts-ignore card.appendChild(placeAutocomplete); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card); // Create the marker and infowindow marker = new google.maps.marker.AdvancedMarkerElement({ map, }); infoWindow = new google.maps.InfoWindow({}); // Add the gmp-placeselect listener, and display the results on the map. //@ts-ignore placeAutocomplete.addEventListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + "</span><br />" + '<span id="place-address">' + place.formattedAddress + "</span>" + "</div>"; updateInfoWindow(content, place.location); marker.position = place.location; }); } // Helper function to create an info window. function updateInfoWindow(content, center) { infoWindow.setContent(content); infoWindow.setPosition(center); infoWindow.open({ map, anchor: marker, shouldFocus: false, }); } initMap();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #place-autocomplete-card { background-color: #fff; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; margin: 10px; padding: 5px; font-family: Roboto, sans-serif; font-size: large; font-weight: bold; } gmp-place-autocomplete { width: 300px; } #infowindow-content .title { font-weight: bold; } #map #infowindow-content { display: inline; }
HTML
<html> <head> <title>Place Autocomplete map</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div class="place-autocomplete-card" id="place-autocomplete-card"> <p>Search for a place here:</p> </div> <div id="map"></div> <!-- prettier-ignore --> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "beta"});</script> </body> </html>
測試範例
使用 Place Picker 元件
Place Picker 元件是輸入文字,可讓使用者透過自動完成功能搜尋特定地址或地點。這是擴充元件程式庫的一部分,這組網頁元件可協助開發人員更快速地製作出色的地圖和位置功能。
使用 Place Picker 設定工具為自訂 Place Picker 元件建立可嵌入的程式碼,然後匯出該程式碼,以便與 React 和 Angular 等熱門架構 (或完全不使用架構) 搭配使用。