Place Autocomplete Data API 可讓您擷取地點預測結果 透過程式化的方式建立自訂自動完成體驗,並進一步掌控 而不是自動完成小工具本指南將說明如何使用 Place Autocomplete Data API,根據使用者提出自動完成要求 舉個簡單的例子,您可以定義情境 並指示 AI 如何回應服務中心查詢
以下範例顯示一種簡易的預先輸入整合方式。輸入搜尋查詢,然後按一下 選取所需結果
Autocomplete 要求
自動完成要求會採用查詢字串,並傳回地點預測結果清單。目的地:
發出 Autocomplete 要求,請呼叫 fetchAutocompleteSuggestions()
並傳遞含有所需屬性的要求input
屬性包含要搜尋的字串;在一般應用程式中,這個值會更新為
使用者輸入查詢要求中應包含 sessionToken
、
用於計費
下列程式碼片段說明如何建立要求主體並新增工作階段符記,然後呼叫
fetchAutocompleteSuggestions()
可取得
PlacePrediction
。
// Add an initial request body. let request = { input: "Tadi", locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78, }, origin: { lat: 37.7893, lng: -122.4039 }, includedPrimaryTypes: ["restaurant"], language: "en-US", region: "us", }; // Create a session token. const token = new AutocompleteSessionToken(); // Add the token to the request. // @ts-ignore request.sessionToken = token;
限制 Autocomplete 預測結果
根據預設,Place Autocomplete 會顯示所有地點類型 (優先顯示使用者所在位置附近的預測結果),並擷取使用者所選地點的所有可用資料欄位。設定地點 自動完成選項可限製或自訂調整結果,顯示更相關的預測結果。
限制結果後,Autocomplete 小工具會略過不在 限制區域。常見做法是將結果限制在地圖範圍內。自訂調整結果 會讓「自動完成」小工具顯示指定區域內的結果,但可能有些符合
使用 origin
屬性指定要計算的起點
與目的地的測地距離。如果省略此值,則不會傳回距離。
使用 includedPrimaryTypes
屬性可指定最多五個地點類型。
如果沒有指定型別,會傳回所有型別的地點。
取得 Place Details
如何傳回Place
物件傳回地點預測結果時,首先呼叫 toPlace()
。
然後呼叫 fetchFields()
產生的 Place
物件上 (系統會自動加入地點預測結果的工作階段 ID)。呼叫 fetchFields()
後,
自動完成工作階段。
let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place. await place.fetchFields({ fields: ["displayName", "formattedAddress"], }); const placeInfo = document.getElementById("prediction"); placeInfo.textContent = "First predicted place: " + place.displayName + ": " + place.formattedAddress;
工作階段符記
工作階段符記會將使用者自動完成搜尋的查詢和選取階段歸入 獨立工作階段用於計費工作階段是從使用者開始輸入時起算, 當使用者選取地點並呼叫 Place Details 時,工作階段就會結束。
如要建立新的工作階段符記並加到要求中,請建立
AutocompleteSessionToken
、
然後設定 sessionToken
屬性,並使用權杖,如以下程式碼片段所示:
// Create a session token. const token = new AutocompleteSessionToken(); // Add the token to the request. // @ts-ignore request.sessionToken = token;
工作階段會在fetchFields()
時結束
方法。建立 Place
執行個體後,不需要傳遞工作階段
權杖設為 fetchFields()
,因為這項操作會自動處理。
await place.fetchFields({ fields: ["displayName", "formattedAddress"], });
await place.fetchFields({ fields: ['displayName'], });
建立新的 AutocompleteSessionToken
執行個體,為下一個工作階段建立工作階段符記。
工作階段符記建議:
- 對所有 Place Autocomplete 呼叫使用工作階段符記。
- 為每個工作階段產生新的權杖。
- 為每個新的工作階段傳遞專屬的工作階段符記。在多個工作階段使用相同符記 因此會分別收取每項要求的費用。
您可以選擇在要求中省略自動完成工作階段符記。如果工作階段符記 則系統會分別收取每項要求的費用,觸發 自動完成 - 按要求計費 SKU。假如您重複使用工作階段符記,系統會將該工作階段視為無效,並依據要求收費 因為沒有提供工作階段符記
範例
當使用者輸入查詢時,系統每隔幾次就呼叫自動完成要求。 並傳回可能結果清單。 使用者從結果清單中選取所需項目時,所選項目會計為 系統傳送要求和所有在搜尋期間提出的要求 就算是一次請求如果使用者選取某個地點,搜尋查詢就會是 免付費使用,且只需為「地點」資料要求付費。如果使用者未在 而是在練習開始的幾分鐘前選取 才需付費
從應用程式的角度來看,事件流程如下:
- 使用者開始輸入查詢,以搜尋「法國巴黎」。
- 偵測到使用者輸入內容時,應用程式會建立新的工作階段 「憑證 A」
- 當使用者輸入內容時,API 每隔幾毫秒就會提出自動完成要求
字元,因此會顯示一份新清單,其中列出各項目可能的結果:
「P」
「Par」
「巴黎」
「巴黎, Fr」
- 使用者做出選擇後:
- 系統會將查詢產生的所有要求加入群組,並新增至 以「權杖 A」表示,做為單一要求。
- 使用者的選擇會計為 Place Details 要求,且新增了 加入「權杖 A」代表的工作階段
- 工作階段已結束,應用程式會捨棄「權杖 A」。
完整程式碼範例
本節包含如何使用 Place Autocomplete Data API 的完整範例。Place Autocomplete 預測結果
以下範例示範如何呼叫
fetchAutocompleteSuggestions()
敬上
,然後呼叫 toPlace()
,
,接著呼叫 fetchFields()
以取得地點詳細資料。
TypeScript
/** * Demonstrates making a single request for Place predictions, then requests Place Details for the first result. */ async function init() { // @ts-ignore const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary; // Add an initial request body. let request = { input: "Tadi", locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 }, origin: { lat: 37.7893, lng: -122.4039 }, includedPrimaryTypes: ["restaurant"], language: "en-US", region: "us", }; // Create a session token. const token = new AutocompleteSessionToken(); // Add the token to the request. // @ts-ignore request.sessionToken = token; // Fetch autocomplete suggestions. const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request); const title = document.getElementById('title') as HTMLElement; title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":')); for (let suggestion of suggestions) { const placePrediction = suggestion.placePrediction; // Create a new list element. const listItem = document.createElement('li'); const resultsElement = document.getElementById("results") as HTMLElement; listItem.appendChild(document.createTextNode(placePrediction.text.toString())); resultsElement.appendChild(listItem); } let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place. await place.fetchFields({ fields: ['displayName', 'formattedAddress'], }); const placeInfo = document.getElementById("prediction") as HTMLElement; placeInfo.textContent = 'First predicted place: ' + place.displayName + ': ' + place.formattedAddress; } init();
JavaScript
/** * Demonstrates making a single request for Place predictions, then requests Place Details for the first result. */ async function init() { // @ts-ignore const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places"); // Add an initial request body. let request = { input: "Tadi", locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78, }, origin: { lat: 37.7893, lng: -122.4039 }, includedPrimaryTypes: ["restaurant"], language: "en-US", region: "us", }; // Create a session token. const token = new AutocompleteSessionToken(); // Add the token to the request. // @ts-ignore request.sessionToken = token; // Fetch autocomplete suggestions. const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request); const title = document.getElementById("title"); title.appendChild( document.createTextNode('Query predictions for "' + request.input + '":'), ); for (let suggestion of suggestions) { const placePrediction = suggestion.placePrediction; // Create a new list element. const listItem = document.createElement("li"); const resultsElement = document.getElementById("results"); listItem.appendChild( document.createTextNode(placePrediction.text.toString()), ); resultsElement.appendChild(listItem); } let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place. await place.fetchFields({ fields: ["displayName", "formattedAddress"], }); const placeInfo = document.getElementById("prediction"); placeInfo.textContent = "First predicted place: " + place.displayName + ": " + place.formattedAddress; } init();
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; }
HTML
<html> <head> <title>Place Autocomplete Data API Predictions</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="title"></div> <ul id="results"></ul> <p><span id="prediction"></span></p> <img class="powered-by-google" src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png" alt="Powered by Google" /> <!-- 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: "weekly"});</script> </body> </html>
測試範例
使用工作階段預先輸入自動完成功能
這個範例示範如何呼叫
fetchAutocompleteSuggestions()
敬上
根據使用者查詢內容,在回應中顯示預測地點清單,最後
選取的地點詳細資料。此範例也示範如何將工作階段符記用於
使用最終的 Place Details 要求,將使用者查詢分組。
TypeScript
let title; let results; let input; let token; // Add an initial request body. let request = { input: "", locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 }, origin: { lat: 37.7893, lng: -122.4039 }, includedPrimaryTypes: ["restaurant"], language: "en-US", region: "us", }; async function init() { token = new google.maps.places.AutocompleteSessionToken(); title = document.getElementById('title'); results = document.getElementById('results'); input = document.querySelector("input"); input.addEventListener("input", makeAcRequest); request = refreshToken(request) as any; } async function makeAcRequest(input) { // Reset elements and exit if an empty string is received. if (input.target.value == '') { title.innerText = ''; results.replaceChildren(); return; } // Add the latest char sequence to the request. request.input = input.target.value; // Fetch autocomplete suggestions and show them in a list. // @ts-ignore const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request); title.innerText = 'Query predictions for "' + request.input + '"'; // Clear the list first. results.replaceChildren(); for (const suggestion of suggestions) { const placePrediction = suggestion.placePrediction; // Create a link for the place, add an event handler to fetch the place. const a = document.createElement('a'); a.addEventListener('click', () => { onPlaceSelected(placePrediction!.toPlace()); }); a.innerText = placePrediction!.text.toString(); // Create a new list element. const li = document.createElement('li'); li.appendChild(a); results.appendChild(li); } } // Event handler for clicking on a suggested place. async function onPlaceSelected(place) { await place.fetchFields({ fields: ['displayName', 'formattedAddress'], }); let placeText = document.createTextNode(place.displayName + ': ' + place.formattedAddress); results.replaceChildren(placeText); title.innerText = 'Selected Place:'; input.value = ''; refreshToken(request); } // Helper function to refresh the session token. async function refreshToken(request) { // Create a new session token and add it to the request. token = new google.maps.places.AutocompleteSessionToken(); request.sessionToken = token; return request; } declare global { interface Window { init: () => void; } } window.init = init;
JavaScript
let title; let results; let input; let token; // Add an initial request body. let request = { input: "", locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78, }, origin: { lat: 37.7893, lng: -122.4039 }, includedPrimaryTypes: ["restaurant"], language: "en-US", region: "us", }; async function init() { token = new google.maps.places.AutocompleteSessionToken(); title = document.getElementById("title"); results = document.getElementById("results"); input = document.querySelector("input"); input.addEventListener("input", makeAcRequest); request = refreshToken(request); } async function makeAcRequest(input) { // Reset elements and exit if an empty string is received. if (input.target.value == "") { title.innerText = ""; results.replaceChildren(); return; } // Add the latest char sequence to the request. request.input = input.target.value; // Fetch autocomplete suggestions and show them in a list. // @ts-ignore const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions( request, ); title.innerText = 'Query predictions for "' + request.input + '"'; // Clear the list first. results.replaceChildren(); for (const suggestion of suggestions) { const placePrediction = suggestion.placePrediction; // Create a link for the place, add an event handler to fetch the place. const a = document.createElement("a"); a.addEventListener("click", () => { onPlaceSelected(placePrediction.toPlace()); }); a.innerText = placePrediction.text.toString(); // Create a new list element. const li = document.createElement("li"); li.appendChild(a); results.appendChild(li); } } // Event handler for clicking on a suggested place. async function onPlaceSelected(place) { await place.fetchFields({ fields: ["displayName", "formattedAddress"], }); let placeText = document.createTextNode( place.displayName + ": " + place.formattedAddress, ); results.replaceChildren(placeText); title.innerText = "Selected Place:"; input.value = ""; refreshToken(request); } // Helper function to refresh the session token. async function refreshToken(request) { // Create a new session token and add it to the request. token = new google.maps.places.AutocompleteSessionToken(); request.sessionToken = token; return request; } window.init = init;
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; } a { cursor: pointer; text-decoration: underline; color: blue; } input { width: 300px; }
HTML
<html> <head> <title>Place Autocomplete Data API Session</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <input id="input" type="text" placeholder="Search for a place..." /> <div id="title"></div> <ul id="results"></ul> <img class="powered-by-google" src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png" alt="Powered by Google" /> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=init&libraries=places&v=weekly" defer ></script> </body> </html>