ווידג'ט ההשלמה האוטומטית של מקומות יוצר שדה להזנת טקסט, מספק תחזיות של מקומות ברשימת בחירה בממשק המשתמש ומחזיר פרטים של מקומות בתגובה לבחירה של המשתמש. אפשר להשתמש בווידג'ט Place Autocomplete כדי להטמיע בממשק המשתמש של דף האינטרנט השלמה אוטומטית מלאה ועצמאית.
דרישות מוקדמות
כדי להשתמש בהשלמה אוטומטית של מקומות, צריך להפעיל את Places API (חדש) בפרויקט שלכם ב-Google Cloud. פרטים נוספים מופיעים במאמר תחילת העבודה.
מה חדש
השיפורים בהשלמה אוטומטית למקומות:
- ממשק המשתמש של הווידג'ט להשלמה אוטומטית תומך בלוקליזציה אזורית (כולל שפות שנקראות מימין לשמאל), עבור ה-placeholder של קלט הטקסט, הלוגו של רשימת התחזיות והתחזיות של המקומות.
- נגישות משופרת, כולל תמיכה בקוראי מסך ואינטראקציה עם המקלדת.
- ווידג'ט ההשלמה האוטומטית מחזיר את המחלקות החדשות של המקומות כדי לפשט את הטיפול באובייקט שמוחזר.
- שיפור התמיכה במכשירים ניידים ובמסכים קטנים.
- שיפור הביצועים והמראה הגרפי.
הוספת ווידג'ט של השלמה אוטומטית
ווידג'ט ההשלמה האוטומטית יוצר שדה להזנת טקסט, מספק תחזיות של מקומות ברשימת בחירה בממשק המשתמש ומחזיר פרטים על מקומות בתגובה לקליק של משתמש באמצעות מאזין gmp-select
. בסעיף הזה מוסבר איך להוסיף ווידג'ט של השלמה אוטומטית לדף אינטרנט או למפת Google.
הוספת ווידג'ט של השלמה אוטומטית לדף אינטרנט
כדי להוסיף את הווידג'ט של ההשלמה האוטומטית לדף אינטרנט, יוצרים google.maps.places.PlaceAutocompleteElement
חדש ומצרפים אותו לדף כמו בדוגמה הבאה:
TypeScript
// Request needed libraries. 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. 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);
הוספת ווידג'ט של השלמה אוטומטית למפה
אם הכתובת לחיוב שלכם נמצאת מחוץ לאזור הכלכלי האירופי (EEA), אתם יכולים גם להשתמש בווידג'ט של השלמה אוטומטית עם מפת Google.
כדי להוסיף ווידג'ט של השלמה אוטומטית למפה, יוצרים מופע חדש של google.maps.places.PlaceAutocompleteElement
, מוסיפים את PlaceAutocompleteElement
ל-div
ומעבירים אותו למפה כרכיב בקרה בהתאמה אישית, כמו בדוגמה הבאה:
TypeScript
//@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = 'place-autocomplete-input'; placeAutocomplete.locationBias = center; 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'; placeAutocomplete.locationBias = center; const card = document.getElementById('place-autocomplete-card'); //@ts-ignore card.appendChild(placeAutocomplete); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
הגבלת החיזויים להשלמה האוטומטית
כברירת מחדל, השלמה אוטומטית של מקומות מציגה את כל סוגי המקומות, עם הטיה לחיזויים בקרבת המיקום של המשתמש, ומאחזרת את כל שדות הנתונים הזמינים למקום שנבחר על ידי המשתמש. כדי להציג תחזיות רלוונטיות יותר, אפשר להגביל את התוצאות או להטות אותן באמצעות הגדרה של PlaceAutocompleteElementOptions.
הגבלת התוצאות גורמת לווידג'ט של ההשלמה האוטומטית להתעלם מתוצאות שנמצאות מחוץ לאזור ההגבלה. נהוג להגביל את התוצאות לגבולות המפה. הטיה של תוצאות מאפשרת לווידג'ט ההשלמה האוטומטית להציג תוצאות באזור שצוין, אבל יכול להיות שחלק מההתאמות יהיו מחוץ לאזור הזה.
אם לא מספקים גבולות או אזור תצוגה של מפה, ה-API ינסה לזהות את מיקום המשתמש מכתובת ה-IP שלו, ויטה את התוצאות למיקום הזה. מומלץ להגדיר גבולות בכל הזדמנות. אחרת, משתמשים שונים עשויים לקבל תחזיות שונות. כדי לשפר את התחזיות באופן כללי, חשוב לספק אזור תצוגה הגיוני, למשל אזור תצוגה שהגדרתם באמצעות הזזה או שינוי גודל התצוגה במפה, או אזור תצוגה שהוגדר על ידי מפתח על סמך מיקום המכשיר והרדיוס. אם רדיוס לא זמין, 5 ק"מ נחשב כברירת מחדל סבירה להשלמה אוטומטית של מקומות. אל תגדירו אזור תצוגה עם רדיוס אפס (נקודה אחת), אזור תצוגה שרוחבו כמה מטרים בלבד (פחות מ-100 מ'), או אזור תצוגה שמשתרע על פני כדור הארץ.
הגבלת חיפוש מקומות לפי מדינה
כדי להגביל את החיפוש של מקומות למדינה ספציפית אחת או יותר, משתמשים במאפיין includedRegionCodes
כדי לציין את קודי המדינות, כמו שמוצג בקטע הקוד הבא:
const pac = new google.maps.places.PlaceAutocompleteElement({ includedRegionCodes: ['us', 'au'], });
הגבלת חיפוש מקומות לגבולות המפה
כדי להגביל את החיפוש של מקומות לגבולות של מפה, משתמשים במאפיין locationRestrictions
כדי להוסיף את הגבולות, כמו שמוצג בקטע הקוד הבא:
const pac = new google.maps.places.PlaceAutocompleteElement({ locationRestriction: map.getBounds(), });
כשמגבילים את המפה לגבולות מסוימים, חשוב להוסיף listener כדי לעדכן את הגבולות כשהם משתנים:
map.addListener('bounds_changed', () => { autocomplete.locationRestriction = map.getBounds(); });
כדי להסיר את locationRestriction
, מגדירים אותו כnull
.
הטיה בתוצאות החיפוש של מקומות
כדי להטות את תוצאות החיפוש של מקומות באזור מעגלי, משתמשים במאפיין locationBias
ומעבירים רדיוס, כמו שמוצג כאן:
const autocomplete = new google.maps.places.PlaceAutocompleteElement({ locationBias: {radius: 100, center: {lat: 50.064192, lng: -130.605469}}, });
כדי להסיר את locationBias
, מגדירים אותו כnull
.
הגבלת תוצאות החיפוש של מקומות לסוגים מסוימים
כדי להגביל את תוצאות החיפוש של מקומות לסוגים מסוימים של מקומות, משתמשים במאפיין includedPrimaryTypes
ומציינים סוג אחד או יותר, כמו שמוצג כאן:
const autocomplete = new google.maps.places.PlaceAutocompleteElement({ includedPrimaryTypes: ['establishment'], });
רשימה מלאה של הסוגים הנתמכים זמינה בטבלאות A ו-B של סוגי מקומות.
קבלת פרטי מקום
כדי לקבל פרטים על המקום שנבחר, מוסיפים listener gmp-select
ל-PlaceAutocompleteElement
, כמו בדוגמה הבאה:
TypeScript
// Add the gmp-placeselect listener, and display the results. //@ts-ignore placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); selectedPlaceTitle.textContent = 'Selected Place:'; selectedPlaceInfo.textContent = JSON.stringify(place.toJSON(), /* replacer */ null, /* space */ 2); });
בדוגמה הקודמת, מאזין האירועים מחזיר אובייקט של Place class.
מתקשרים אל place.fetchFields()
כדי לקבל את שדות הנתונים של פרטי המקום
שנדרשים לאפליקציה.
המאזין בדוגמה הבאה מבקש מידע על מקום ומציג אותו במפה.
TypeScript
// Add the gmp-placeselect listener, and display the results on the map. //@ts-ignore placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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; });
מפות לדוגמה
בקטע הזה מופיע הקוד המלא של מפות לדוגמה שמוצגות בדף הזה.
רכיב השלמה אוטומטית
בדוגמה הזו מוסיפים ווידג'ט של השלמה אוטומטית לדף אינטרנט, ומציגים את התוצאות של כל מקום שנבחר.
TypeScript
async function initMap(): Promise<void> { // Request needed libraries. 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-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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. 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-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script> </body> </html>
לניסיון
מפת השלמה אוטומטית
בדוגמה הזו מוסבר איך להוסיף ווידג'ט של השלמה אוטומטית למפת Google.
TypeScript
let map: google.maps.Map; let marker: google.maps.marker.AdvancedMarkerElement; let infoWindow: google.maps.InfoWindow; let center = { lat: 40.749933, lng: -73.98633 }; // New York City 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, zoom: 13, mapId: '4504f8b37365c3d0', mapTypeControl: false, }); //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = 'place-autocomplete-input'; placeAutocomplete.locationBias = center; 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-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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; let center = { lat: 40.749933, lng: -73.98633 }; // New York City 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, zoom: 13, mapId: '4504f8b37365c3d0', mapTypeControl: false, }); //@ts-ignore const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement(); //@ts-ignore placeAutocomplete.id = 'place-autocomplete-input'; placeAutocomplete.locationBias = center; 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-select', async ({ placePrediction }) => { const place = placePrediction.toPlace(); 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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script> </body> </html>
לניסיון
שימוש ברכיב Place Picker
רכיב בחירת המקום הוא קלט טקסט שמאפשר למשתמשי קצה לחפש כתובת או מקום ספציפיים באמצעות השלמה אוטומטית. היא חלק מספריית הרכיבים המורחבת, אוסף של רכיבי אינטרנט שעוזרים למפתחים ליצור מפות טובות יותר ותכונות מיקום מהר יותר.
אפשר להשתמש בכלי ההגדרה של בורר המקומות כדי ליצור קוד להטמעה של רכיב מותאם אישית של בורר המקומות, ואז לייצא אותו לשימוש עם מסגרות פופולריות כמו React ו-Angular, או ללא מסגרת בכלל.