באמצעות Place Autocomplete Data API אפשר לאחזר תחזיות של מקומות באופן פרוגרמטי, כדי ליצור חוויות מותאמות אישית של השלמה אוטומטית עם רמת שליטה גבוהה יותר מזו שאפשר לקבל באמצעות הווידג'ט של ההשלמה האוטומטית. במדריך הזה תלמדו איך להשתמש ב-Place Autocomplete Data API כדי לשלוח בקשות להשלמה אוטומטית על סמך שאילתות של משתמשים.
בדוגמה הבאה מוצג שילוב פשוט של תכונת השלמה אוטומטית. מזינים את שאילתת החיפוש ולוחצים על כדי לבחור את התוצאה הרצויה.
השלמה אוטומטית של בקשות
בקשה להשלמה אוטומטית מקבלת מחרוזת קלט של שאילתה ומחזירה רשימה של חיזויים של מקומות. כדי לשלוח בקשה להשלמה אוטומטית, צריך לבצע קריאה ל-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;
הגבלת החיזויים להשלמה האוטומטית
כברירת מחדל, בתכונה'השלמה אוטומטית של מקומות' מוצגים כל סוגי המקומות, עם נטייה לחיזויים ליד המיקום של המשתמש, והמערכת מאחזרת את כל שדות הנתונים הזמינים של המקום שבחר המשתמש. הגדרת האפשרויות של ההשלמה האוטומטית של מקומות כדי להציג תחזיות רלוונטיות יותר, על ידי הגבלת התוצאות או הטיה שלהן.
הגבלת התוצאות גורמת לווידג'ט ההשלמה האוטומטית להתעלם מתוצאות שנמצאות מחוץ לאזור ההגבלה. שיטה נפוצה היא להגביל את התוצאות לגבולות המפה. הטיה של התוצאות גורמת לווידג'ט ההשלמה האוטומטית להציג תוצאות בתוך האזור שצוין, אבל יכול להיות שחלק מההתאמות יהיו מחוץ לאזור הזה.
משתמשים במאפיין origin
כדי לציין את נקודת המוצא שממנה מחושב המרחק הגיאודטי ליעד. אם הערך הזה מושמט, המרחק לא מוחזר.
השתמשו במאפיין includedPrimaryTypes
כדי לציין עד חמישה סוגים של מקומות.
אם לא מציינים סוגים, המערכת תחזיר מקומות מכל הסוגים.
אחזור פרטי מקום
כדי להחזיר אובייקט Place
מתוצאה של חיזוי מיקום, קודם צריך לבצע קריאה ל-toPlace()
ואז לבצע קריאה ל-fetchFields()
באובייקט Place
שנוצר (מזהה הסשן מחיזוי המיקום נכלל באופן אוטומטי). הקריאה ל-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
כדי ליצור אסימון סשן לסשן הבא.
המלצות בנוגע לטוקן לסשן:
- שימוש באסימוני סשן בכל הקריאות להשלמה האוטומטית של מקומות.
- יוצרים טוקן חדש לכל סשן.
- מעבירים אסימון סשן ייחודי לכל סשן חדש. שימוש באותו אסימון ביותר מסשן אחד יביא לחיוב בנפרד על כל בקשה.
אפשר להשמיט את אסימון הסשן של ההשלמה האוטומטית מהבקשה. אם לא תכללו את אסימון הסשן, כל בקשה תחויב בנפרד, ותגרום לחיוב לפי המק"ט Autocomplete – Per Request. אם משתמשים שוב באסימון סשן, הסשן נחשב לא תקף והבקשות יחויבו כאילו לא סופק אסימון סשן.
דוגמה
כשהמשתמש מקלידים שאילתות, המערכת מפעילה בקשה להשלמה אוטומטית אחרי כל כמה הקשות (לא לכל תו) ומציגה רשימה של תוצאות אפשריות. כשהמשתמש בוחר מתוך רשימת התוצאות, הבחירה נספרת כבקשה, וכל הבקשות שנשלחות במהלך החיפוש מקובצות ונספרות כבקשה אחת. אם המשתמש בוחר מקום, שאילתת החיפוש זמינה ללא תשלום, ורק הבקשה לנתוני המקום מחויבת. אם המשתמש לא מבצע בחירה תוך כמה דקות מתחילת הסשן, תחויבו רק על שאילתה החיפוש.
מנקודת המבט של אפליקציה, רצף האירועים הוא:
- משתמש מתחיל להקליד שאילתת חיפוש עבור 'פריז, צרפת'.
- כשהאפליקציה מזהה קלט של משתמש, היא יוצרת טוקן סשן חדש, 'אסימון א'.
- כשהמשתמש מקלידים, ה-API שולח בקשה להשלמה אוטומטית אחרי כל כמה תווים, ומציג רשימה חדשה של תוצאות אפשריות לכל אחד מהם:
"P"
"Par"
"Paris,"
"Paris, Fr"
- כשהמשתמש מבצע בחירה:
- כל הבקשות שנובעות מהשאילתה מקובצות ומתווספות לסשן שמיוצג על ידי אסימון א', כבקשה אחת.
- הבחירה של המשתמש נספרת כבקשה לפרטים של מקום, ומתווספת לסשן שמיוצג על ידי אסימון א'.
- הסשן מסתיים והאפליקציה משליכה את אסימון א'.
קוד לדוגמה מלא
בקטע הזה מפורטות דוגמאות מלאות לשימוש ב-Place Autocomplete Data API .הצעות להשלמה אוטומטית של מקומות
בדוגמה הבאה מוצגת קריאה ל-fetchAutocompleteSuggestions()
עם הקלט 'Tadi', ואז קריאה ל-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()
על סמך שאילתות של משתמשים, הצגת רשימה של מקומות צפויים בתגובה ולבסוף אחזור פרטי המקום שנבחר. הדוגמה גם מדגימה את השימוש באסימוני סשן כדי לקבץ שאילתה של משתמש עם הבקשה הסופית לפרטים של מקום.
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>