ווידג'ט להשלמה אוטומטית של מקומות (תצוגה מקדימה)

הווידג'ט של השלמה אוטומטית של מקומות יוצר שדה קלט טקסט, מספק תחזיות של מקומות ברשימת בחירה בממשק המשתמש ומחזיר פרטי מקומות בתגובה לבחירה של המשתמש. השתמשו בווידג'ט 'השלמה אוטומטית של מקומות' כדי להטמיע ממשק משתמש עצמאי להשלמה אוטומטית בדף האינטרנט שלך.

דרישות מוקדמות

כדי להשתמש בהשלמה האוטומטית של מקומות (גרסת טרום-השקה), צריך להפעיל את Places API בפרויקט ב-Google Cloud ולציין את ערוץ הבטא (v: "beta") ב-bootstrap loader. לפרטים נוספים, ראו תחילת העבודה.

מה חדש

השיפורים בהשלמה האוטומטית למקומות (בטא) הם:

  • ממשק המשתמש של הווידג'ט של ההשלמה האוטומטית תומך בתמיכה אזורית (כולל שפות RTL) ב-placeholder של קלט הטקסט, בלוגו של רשימת התחזיות ובתחזיות המקומות.
  • נגישות משופרת, כולל תמיכה בקוראי מסך ואינטראקציה עם מקלדת.
  • הווידג'ט של ההשלמה האוטומטית מחזיר את סוג המקום החדש כדי לפשט את הטיפול באובייקט המוחזר.
  • תמיכה טובה יותר במכשירים ניידים ובמסכים קטנים.
  • ביצועים טובים יותר ומראה גרפי משופר.

הוספת ווידג'ט של השלמה אוטומטית

אפשר להוסיף ווידג'ט של השלמה אוטומטית לדף אינטרנט או למפה של Google. הווידג'ט של ההשלמה האוטומטית יוצר שדה קלט טקסט, מספק תחזיות של מקומות ברשימת בחירה בממשק המשתמש ומחזיר את פרטי המקום בתגובה לקליק של משתמש באמצעות המאזין gmp-placeselect. בקטע הזה מוסבר איך להוסיף ווידג'ט של השלמה אוטומטית לדף אינטרנט או למפה של Google.

הוספת ווידג'ט של השלמה אוטומטית לדף אינטרנט

כדי להוסיף את הווידג'ט של ההשלמה האוטומטית לדף אינטרנט, יוצרים 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);

הקוד המלא לדוגמה

הוספת ווידג'ט של השלמה אוטומטית למפה

כדי להוסיף למפה ווידג'ט של השלמה אוטומטית, צריך ליצור מופע 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);

הקוד המלא לדוגמה

הגבלת החיזויים להשלמה אוטומטית

כברירת מחדל, ההשלמה האוטומטית של המקום מציגה את כל סוגי המקומות, תוך התייחסות לחיזויים שנמצאים בקרבת המיקום של המשתמש מיקום, ומאחזר את כל שדות הנתונים הזמינים עבור המקום שנבחר על ידי המשתמש. הגדרת מקום אפשרויות להשלמה אוטומטית להצגת חיזויים רלוונטיים יותר על ידי הגבלה או הטייה של התוצאות.

הגבלת התוצאות גורמת לווידג'ט ההשלמה האוטומטית להתעלם מתוצאות שמחוץ לאזור ההגבלה. אחת מהשיטות הנפוצות היא להגביל תוצאות לגבולות המפה. הטיית תוצאות גורם לווידג'ט ההשלמה האוטומטית להציג תוצאות בתוך האזור שצוין, אבל ייתכן שחלק מההתאמות מחוץ לאזור הזה.

הגבלת החיפוש של מקומות לפי מדינה

כדי להגביל את חיפוש המקומות למדינה ספציפית אחת או יותר, יש להשתמש בcomponentRestrictions כדי לציין את קודי המדינה כפי שמוצג בקטע הקוד הבא:

const pac = new google.maps.places.PlaceAutocompleteElement({
  componentRestrictions: {country: ['us', 'au']},
});

הגבלת חיפוש המקומות לגבולות המפה

כדי להגביל את חיפוש המקומות לגבולות של מפה, משתמשים במאפיין locationRestrictions כדי להוסיף את הגבולות, כפי שמתואר בקטע הקוד הבא:

const pac = new google.maps.places.PlaceAutocompleteElement({
  locationRestriction: map.getBounds(),
});

כשמגבילים את החיפוש לגבולות המפה, חשוב להוסיף מאזין כדי לעדכן את הגבולות כשהם משתנים:

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.

הגבלת תוצאות החיפוש של מקומות לסוגים מסוימים

כדי להגביל את תוצאות החיפוש של מקומות לסוגים מסוימים של מקומות, משתמשים במאפיין types ומציינים סוג אחד או יותר, כפי שמתואר כאן:

const autocomplete = new google.maps.places.PlaceAutocompleteElement({
  types: ['establishment'],
});

רשימה מלאה של הסוגים הנתמכים מופיעה בטבלה 3: סוגי הבקשות הנתמכות להשלמה אוטומטית של מקומות.

אחזור פרטי מקום

כדי לקבל את פרטי המקום שנבחר, מוסיפים מאזין gmp-place-select ל-PlaceAutocompleteElement, כפי שמתואר בדוגמה הבאה:

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,
  );
});

הקוד המלא לדוגמה

בדוגמה הקודמת, ה-event listener מחזיר אובייקט של Place class. צריך לבצע קריאה ל-place.fetchFields() כדי לקבל את שדות הנתונים של פרטי המקום שנדרשים לאפליקציה.

בדוגמה הבאה, ה-listener מבקש מידע על מקום ומציג אותם במפה.

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;
});

דוגמה לקוד המלא

קבלת תוצאות של המרה של כתובת לקואורדינטות (geocoding) עבור המקום שנבחר

כדי לקבל תוצאות של קידוד גיאוגרפי למקום הנבחר, צריך להשתמש ב-google.maps.Geocoder כדי לקבל את המיקום, כפי שמוצג בקטע הקוד הבא:

const map = new google.maps.Map(document.getElementById('map'), {
  center: {lat: 50.064192, lng: -130.605469},
  zoom: 3,
});

const marker = new google.maps.Marker({map});
const autocomplete = new google.maps.places.PlaceAutocompleteElement();
const geocoder = new google.maps.Geocoder();

autocomplete.addListener('gmp-placeselect', async ({prediction: place}) => {
  const results = await geocoder.geocode({place.id});
  marker.setPlace({
    placeId: place.id,
    location: results[0].geometry.location,
  });
});

מפות לדוגמה

קטע זה מכיל את הקוד המלא עבור המפות לדוגמה המוצגות בדף זה.

רכיב של השלמה אוטומטית

בדוגמה הזו מתווסף ווידג'ט של השלמה אוטומטית לדף אינטרנט, והתוצאות מוצגות לכל מקום שנבחר.

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.

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>

כדאי לנסות דוגמה

שימוש ברכיב 'בחירת מקום'

הרכיב של בוחר המקומות הוא קלט טקסט שמאפשר למשתמשי קצה לחפש כתובת או מקום ספציפיים באמצעות השלמה אוטומטית. הוא חלק מExtended Component Library, קבוצה של רכיבי אינטרנט שעוזרים למפתחים ליצור מפות ותכונות מיקום טובות יותר מהר יותר.

אתם יכולים להשתמש בכלי להגדרת בורר המקומות כדי ליצור קוד שניתן להטמעה לרכיב בורר מקומות מותאם אישית, ולאחר מכן לייצא אותו לשימוש עם מסגרות פופולריות כמו React ו-Angular, או בלי מסגרת בכלל.