Tiện ích tự động hoàn thành địa điểm (Bản xem trước)

Tiện ích tự động hoàn thành địa điểm sẽ tạo một trường nhập dữ liệu văn bản, cung cấp các thông tin dự đoán về địa điểm trong danh sách chọn giao diện người dùng và trả về thông tin chi tiết về địa điểm để phản hồi lựa chọn của người dùng. Sử dụng Tiện ích tự động hoàn thành địa điểm để nhúng giao diện người dùng tự động hoàn thành độc lập hoàn chỉnh vào trang web của bạn.

Điều kiện tiên quyết

Để sử dụng tính năng Tự động hoàn thành địa điểm (Xem trước), bạn phải bật "API địa điểm" trong dự án Google Cloud và chỉ định kênh beta (v: "beta") trong trình tải khởi động. Hãy xem bài viết Bắt đầu để biết thông tin chi tiết.

Tính năng mới

Tính năng Tự động hoàn thành địa điểm (Xem trước) đã được cải tiến theo những cách sau:

  • Giao diện người dùng của tiện ích Tự động hoàn thành hỗ trợ bản địa hoá theo khu vực (bao gồm cả các ngôn ngữ RTL), cho phần giữ chỗ nhập văn bản, biểu trưng của danh sách cụm từ gợi ý và thông tin dự đoán về địa điểm.
  • Cải thiện tính năng hỗ trợ tiếp cận, trong đó có tính năng hỗ trợ trình đọc màn hình và hoạt động tương tác với bàn phím.
  • Tiện ích Tự động hoàn thành sẽ trả về Place class (Lớp địa điểm) mới để đơn giản hoá việc xử lý đối tượng được trả về.
  • Hỗ trợ tốt hơn cho thiết bị di động và màn hình nhỏ.
  • Hiệu suất tốt hơn và giao diện đồ hoạ được cải thiện.

Thêm tiện ích Tự động hoàn thành

Bạn có thể thêm tiện ích Tự động hoàn thành vào một trang web hoặc bản đồ Google. Tiện ích Tự động hoàn thành sẽ tạo một trường nhập dữ liệu văn bản, đưa ra các thông tin dự đoán về vị trí trong danh sách chọn giao diện người dùng và trả về thông tin chi tiết về địa điểm để phản hồi một lượt nhấp của người dùng thông qua trình nghe gmp-placeselect. Phần này hướng dẫn bạn cách thêm một tiện ích tự động hoàn thành vào một trang web hoặc một bản đồ của Google.

Thêm tiện ích Tự động hoàn thành vào trang web

Để thêm tiện ích Tự động hoàn thành vào một trang web, hãy tạo một google.maps.places.PlaceAutocompleteElement mới và thêm tiện ích này vào trang như trong ví dụ sau:

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

Xem mã ví dụ hoàn chỉnh

Thêm tiện ích Tự động hoàn thành vào bản đồ

Để thêm một tiện ích Tự động hoàn thành vào bản đồ, hãy tạo một thực thể google.maps.places.PlaceAutocompleteElement mới, thêm PlaceAutocompleteElement vào một div và đẩy tiện ích này vào bản đồ dưới dạng một thành phần điều khiển tuỳ chỉnh, như trong ví dụ sau:

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

Xem mã ví dụ hoàn chỉnh

Giới hạn các cụm từ gợi ý của tính năng Tự động hoàn thành

Theo mặc định, tính năng Tự động hoàn thành địa điểm sẽ hiển thị mọi loại địa điểm, thiên về các cụm từ gợi ý gần vị trí của người dùng và tìm nạp mọi trường dữ liệu có sẵn cho địa điểm mà người dùng đã chọn. Đặt các tuỳ chọn Tự động hoàn thành về địa điểm để đưa ra thông tin dự đoán phù hợp hơn bằng cách hạn chế hoặc xu hướng kết quả.

Việc hạn chế kết quả sẽ khiến tiện ích Tự động hoàn thành bỏ qua mọi kết quả nằm ngoài vùng hạn chế. Một phương pháp phổ biến là giới hạn kết quả ở ranh giới bản đồ. Kết quả xu hướng giúp tiện ích Tự động hoàn thành hiển thị kết quả trong khu vực được chỉ định, nhưng một số kết quả phù hợp có thể nằm ngoài khu vực đó.

Hạn chế tìm kiếm địa điểm theo quốc gia

Để hạn chế tính năng tìm kiếm địa điểm ở một hoặc nhiều quốc gia cụ thể, hãy sử dụng thuộc tính componentRestrictions để chỉ định(các) mã quốc gia như trong đoạn mã sau:

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

Giới hạn tìm kiếm địa điểm trong phạm vi bản đồ

Để giới hạn tính năng tìm kiếm địa điểm ở các ranh giới của bản đồ, hãy sử dụng thuộc tính locationRestrictions để thêm các giới hạn, như minh hoạ trong đoạn mã sau:

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

Khi giới hạn ở ranh giới ánh xạ, hãy nhớ thêm trình nghe để cập nhật các ranh giới khi chúng thay đổi:

map.addListener('bounds_changed', () => {
  autocomplete.locationRestriction = map.getBounds();
});

Để xoá locationRestriction, hãy đặt thành null.

Kết quả tìm kiếm địa điểm thiên vị

Định vị kết quả tìm kiếm cho một khu vực hình tròn bằng cách sử dụng thuộc tính locationBias và truyền một bán kính, như minh hoạ dưới đây:

const autocomplete = new google.maps.places.PlaceAutocompleteElement({
  locationBias: {radius: 100, center: {lat: 50.064192, lng: -130.605469}},
});

Để xoá locationBias, hãy đặt thành null.

Hạn chế kết quả tìm kiếm địa điểm ở một số loại nhất định

Hãy giới hạn kết quả tìm kiếm địa điểm ở một số loại địa điểm nhất định bằng cách sử dụng thuộc tính types và chỉ định một hoặc nhiều loại địa điểm như sau:

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

Để biết danh sách đầy đủ các loại được hỗ trợ, hãy xem Bảng 3: Các loại được hỗ trợ trong yêu cầu tự động hoàn thành theo vị trí.

Lấy thông tin chi tiết về địa điểm

Để biết thông tin chi tiết về địa điểm cho địa điểm đã chọn, hãy thêm trình nghe gmp-place-select vào PlaceAutocompleteElement như trong ví dụ sau:

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

Xem mã ví dụ hoàn chỉnh

Trong ví dụ trước, trình nghe sự kiện trả về một đối tượng của Lớp địa điểm. Gọi place.fetchFields() để lấy các trường dữ liệu Chi tiết về địa điểm cần thiết cho ứng dụng của bạn.

Trình nghe ở ví dụ tiếp theo sẽ yêu cầu đặt thông tin và hiển thị thông tin đó trên bản đồ.

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

Xem mã ví dụ hoàn chỉnh

Nhận kết quả mã hoá địa lý cho địa điểm đã chọn

Để nhận kết quả mã hoá địa lý cho địa điểm đã chọn, hãy sử dụng google.maps.Geocoder để nhận vị trí, như minh hoạ trong đoạn mã sau:

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

Bản đồ mẫu

Phần này chứa mã hoàn chỉnh cho các bản đồ mẫu được nêu trên trang này.

Phần tử tự động hoàn thành

Ví dụ này sẽ thêm một tiện ích Tự động hoàn thành vào một trang web và hiển thị kết quả cho từng địa điểm đã chọn.

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>

Thử dùng mẫu

Tự động hoàn thành bản đồ

Ví dụ này cho bạn biết cách thêm một tiện ích Tự động hoàn thành vào bản đồ 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>

Thử dùng mẫu

Sử dụng thành phần Bộ chọn địa điểm

Lưu ý: Mẫu này sử dụng thư viện nguồn mở. Hãy xem phần README để được hỗ trợ và phản hồi liên quan đến thư viện.

Thành phần bộ chọn địa điểm là một mục nhập văn bản cho phép người dùng cuối tìm kiếm một địa chỉ hoặc địa điểm cụ thể bằng tính năng tự động hoàn thành. Thư viện thành phần mở rộng (Extended Component Library) là một tập hợp các thành phần web giúp nhà phát triển tạo các tính năng định vị và bản đồ tốt hơn một cách nhanh hơn.

Cấu hình Bộ chọn địa điểm

Sử dụng trình cấu hình để tạo mã có thể nhúng cho một thành phần Bộ chọn địa điểm tuỳ chỉnh, sau đó xuất mã này để dùng với các khung phổ biến như React và Angular hoặc không có khung nào.

Bắt đầu

Để bắt đầu, hãy tải thư viện Thành phần mở rộng bằng npm.

Để có hiệu suất tốt nhất, hãy sử dụng trình quản lý gói và chỉ nhập các thành phần bạn cần. Gói này có tên npm là @googlemaps/Expand-component-library. Cài đặt bằng:

  npm i @googlemaps/extended-component-library;

Sau đó, hãy nhập mọi thành phần mà bạn dùng trong ứng dụng.

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

Sau khi tải thư viện npm, hãy lấy khoá API từ Cloud Console.

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

Sử dụng thẻ thành phần bộ chọn địa điểm.

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

Để biết thêm thông tin chi tiết, hãy truy cập vào GitHub hoặc npm. Để xem các thành phần dùng trong mã mẫu, hãy xem trang ví dụ trên GitHub.