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

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

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

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

מה חדש

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

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

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

אתם יכולים להוסיף ווידג'ט של השלמה אוטומטית לדף אינטרנט או למפה של Google. הווידג'ט של ההשלמה האוטומטית יוצר שדה להזנת טקסט, אספקה של חיזויים ברשימה לבחירת ממשק משתמש, ומחזירה פרטי מקום תגובה לקליק של משתמש דרך ה-listener 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;
});

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

קבלת תוצאות של קידוד גיאוגרפי עבור המקום שנבחר

כדי לקבל תוצאות של קידוד גיאוגרפי למקום הנבחר, צריך להשתמש ב-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>

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

שימוש ברכיב של בוחר המקומות

הערה: הדוגמה הזו מתבססת על ספריית קוד פתוח. לצפייה README לקבלת תמיכה ומשוב שקשור לספרייה.

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

מגדיר המקום של בוחר המקומות

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

תחילת העבודה

כדי להתחיל, צריך לטעון את ספריית הרכיבים המורחבים עם npm.

לקבלת הביצועים הטובים ביותר, יש להשתמש במנהל חבילות ולייבא רק את הרכיבים הדרושים לך. החבילה הזו רשומה ב-npm בתור @googlemaps/extended-component-library. התקנת האפליקציה באמצעות:

  npm i @googlemaps/extended-component-library;

לאחר מכן ייבאו את הרכיבים שבהם אתם משתמשים באפליקציה.

  import '@googlemaps/extended-component-library/place_picker.js';

אחרי שטוענים את ספריית ה-NPM, לקבל מפתח API ממסוף Cloud.

  <gmpx-api-loader key="YOUR_API_KEY" solution-channel="GMP_DOCS_placepicker_v1"></gmpx-api-loader>

להשתמש בתג הרכיב של בוחר המקומות.

  <gmpx-place-picker placeholder="Enter a place" id="place-picker" style="width: 100%">
  </gmpx-place-picker>

לפרטים נוספים, אפשר לעיין במאמר GitHub או npm. כדי לראות רכיבים שנעשה בהם שימוש בקוד לדוגמה, כדאי לעיין examples ב-GitHub.