Phần tử cơ bản của tính năng Place Autocomplete

BasicPlaceAutocompleteElement tạo một trường nhập văn bản, cung cấp các dự đoán về địa điểm trong danh sách chọn trên giao diện người dùng và trả về mã địa điểm cho địa điểm đã chọn.

Ngược lại với PlaceAutocompleteElement, phần tử Basic Place Autocomplete (Tự động hoàn thành thông tin cơ bản về địa điểm) được đơn giản hoá sẽ xoá trường nhập khi người dùng chọn một cụm từ dự đoán về địa điểm, đồng thời trả về một đối tượng Place (Địa điểm) chỉ chứa place ID (mã địa điểm), thay vì một đối tượng PlacePrediction. Sử dụng Mã địa điểm này với một phần tử Thông tin chi tiết về Places UI Kit để nhận thêm thông tin chi tiết về địa điểm.

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

Để sử dụng phần tử Cơ bản của tính năng Tự động hoàn thành địa điểm, bạn phải bật "Places UI Kit" trên dự án Google Cloud của mình. Hãy xem phần Bắt đầu sử dụng để biết thông tin chi tiết.

Thêm một phần tử Cơ bản cho tính năng Tự động hoàn thành địa điểm

Phần tử Cơ bản về tính năng tự động hoàn thành địa điểm sẽ tạo một trường nhập văn bản, cung cấp các dự đoán về địa điểm trong danh sách chọn trên giao diện người dùng và trả về mã địa điểm để phản hồi lựa chọn của người dùng bằng sự kiện gmp-select. Phần này hướng dẫn bạn cách thêm một phần tử Tự động hoàn thành cơ bản vào trang web hoặc bản đồ.

Thêm phần tử Basic Autocomplete (Tự động hoàn thành cơ bản) vào trang web

Để thêm phần tử BasicAutocomplete vào một trang web, hãy tạo một google.maps.places.BasicPlaceAutocompleteElement mới và nối phần tử đó vào trang như minh hoạ trong ví dụ sau:

  // Request needed libraries.
const {BasicPlaceAutocompleteElement} = await google.maps.importLibrary('places');
// Create the input HTML element, and append it.
const placeAutocomplete = new BasicPlaceAutocompleteElement();
document.body.appendChild(placeAutocomplete);

Thêm phần tử Tự động hoàn thành cơ bản vào bản đồ

Để thêm phần tử Tự động hoàn thành cơ bản vào bản đồ, hãy tạo một thực thể BasicPlaceAutocompleteElement mới, nối thực thể đó vào div và đẩy thực thể đó lên bản đồ dưới dạng một chế độ kiểm soát tuỳ chỉnh, như trong ví dụ sau:

  const placeAutocomplete = new google.maps.places.BasicPlaceAutocompleteElement();
  placeAutocomplete.id = 'place-autocomplete-input';
  placeAutocomplete.locationBias = center;
  const card = document.getElementById('place-autocomplete-card');
  card.appendChild(placeAutocomplete);
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);

Hạn chế 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 cơ bản sẽ trình bày tất cả các loại địa điểm, thiên về những dự đoán gần vị trí của người dùng. Đặt BasicPlaceAutocompleteElementOptions để đưa ra những dự đoán phù hợp hơn bằng cách hạn chế hoặc thiên vị kết quả.

Việc hạn chế kết quả khiến phần tử Tự động hoàn thành cơ bản bỏ qua mọi kết quả nằm ngoài khu vực hạn chế. Một phương pháp thường dùng là hạn chế kết quả trong phạm vi ranh giới trên bản đồ. Việc điều chỉnh kết quả khiến phần tử BasicAutocomplete hiển thị kết quả trong khu vực được chỉ định, nhưng một số kết quả trùng khớp có thể nằm ngoài khu vực đó.

Nếu bạn không cung cấp bất kỳ ranh giới hoặc khung hiển thị bản đồ nào, API sẽ cố gắng phát hiện vị trí của người dùng từ địa chỉ IP của họ và sẽ điều chỉnh kết quả theo vị trí đó. Đặt ranh giới bất cứ khi nào có thể. Nếu không, những người dùng khác nhau có thể nhận được những dự đoán khác nhau. Ngoài ra, để cải thiện các dự đoán nói chung, bạn cần cung cấp một khung hiển thị hợp lý, chẳng hạn như khung hiển thị mà bạn đặt bằng cách di chuyển hoặc thu phóng trên bản đồ, hoặc khung hiển thị do nhà phát triển đặt dựa trên vị trí và bán kính của thiết bị. Khi không có bán kính, 5 km được coi là giá trị mặc định hợp lý cho phần tử Cơ bản của tính năng Tự động hoàn thành địa điểm. Không đặt khung hiển thị có bán kính bằng 0 (một điểm duy nhất), khung hiển thị chỉ rộng vài mét (dưới 100 m) hoặc khung hiển thị trải rộng trên toàn cầu.

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

Để hạn chế 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 includedRegionCodes để chỉ định(các) mã quốc gia như minh hoạ trong đoạn mã sau:

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

Hạn chế tìm kiếm địa điểm trong ranh giới trên bản đồ

Để hạn chế tìm kiếm địa điểm trong phạm vi của bản đồ, hãy dùng thuộc tính locationRestrictions để thêm phạm vi, như minh hoạ trong đoạn mã sau:

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

Khi hạn chế theo ranh giới bản đồ, hãy nhớ thêm một trình nghe để cập nhật ranh giới khi ranh giới 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ị

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

const autocomplete = new google.maps.places.BasicPlaceAutocompleteElement({
  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 đối với một số loại nhất định

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

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

Để xem danh sách đầy đủ các loại được hỗ trợ, hãy xem Bảng A và B về loại địa điểm.

Nhận thông tin chi tiết về địa điểm

Để lấy mã địa điểm cho địa điểm đã chọn, hãy thêm một trình nghe gmp-select vào PlaceAutocompleteElement, như trong ví dụ sau:

// Add the gmp-select listener, and display the results.
  placeAutocomplete.addEventListener('gmp-select', async ({ place }) => {
      await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] });
      selectedPlaceTitle.textContent = 'Selected Place:';
      selectedPlaceInfo.textContent = JSON.stringify(place.toJSON(), /* replacer */ null, /* space */ 2);
  });
  

Trong ví dụ trước, trình nghe sự kiện sẽ trả về một đối tượng thuộc lớp Place. 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 trong ví dụ tiếp theo yêu cầu thông tin về địa điểm và hiển thị thông tin đó trên bản đồ.

  // Add the gmp-placeselect listener, and display the results on the map.
  //@ts-ignore
  placeAutocomplete.addEventListener('gmp-select', 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;
  });
  

Ví dụ này cho thấy cách thêm phần tử Tự động hoàn thành cơ bản vào một bản đồ Google.

JavaScript

const mapContainer = document.getElementById("map-container");
const autocompleteElement = document.querySelector('gmp-basic-place-autocomplete');
const detailsElement = document.querySelector('gmp-place-details-compact');
const mapElement = document.querySelector('gmp-map');
const advancedMarkerElement = document.querySelector('gmp-advanced-marker');
let center = { lat: 40.749933, lng: -73.98633 }; // New York City
async function initMap() {
    //@ts-ignore
    const { BasicPlaceAutocompleteElement, PlaceDetailsElement } = await google.maps.importLibrary('places');
    //@ts-ignore
    const { AdvancedMarkerElement } = await google.maps.importLibrary('marker');
    //@ts-ignore
    const { LatLngBounds } = await google.maps.importLibrary('core');
    // Set the initial map location and autocomplete location bias
    mapElement.center = center;
    autocompleteElement.locationBias = center;
    // Get the underlying google.maps.Map object to add listeners
    const map = mapElement.innerMap;
    // Add the listener tochange locationBias to locationRestriction when the map moves
    map.addListener('bounds_changed', () => {
        autocompleteElement.locationBias = null;
        autocompleteElement.locationRestriction = map.getBounds();
        console.log("bias changed to restriction");
    });
    // Add the listener to update the Place Request element when the user selects a prediction
    autocompleteElement.addEventListener('gmp-select', async (event) => {
        const placeDetailsRequest = document.querySelector('gmp-place-details-place-request');
        placeDetailsRequest.place = event.place.id;
    });
    // Add the listener to update the marker when the Details element loads
    detailsElement.addEventListener('gmp-load', async () => {
        const location = detailsElement.place.location;
        detailsElement.style.display = "block";
        advancedMarkerElement.position = location;
        advancedMarkerElement.content = detailsElement;
        if (detailsElement.place.viewport) {
            map.fitBounds(detailsElement.place.viewport);
        }
        else {
            map.setCenter(location);
            map.setZoom(17);
        }
    });
}
initMap();

CSS

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#map-container {
  display: flex;
  flex-direction: row;
  height: 100%;
}

#gmp-map {
  height: 100%;
}

gmp-basic-place-autocomplete {
  position: absolute;
  height: 50px;
  top: 10px;
  left: 10px;
  z-index: 1;
  box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.2); 
  color-scheme: light;
  border-radius: 10px;
}

gmp-place-details-compact {
  width: 360px;
  max-height: 300px;
  border: none;
  padding: 0;
  margin: 0;
  position: absolute;
  transform: translate(calc(-180px), calc(-215px)); 
  box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.2); 
  color-scheme: light;
}

/* This creates the pointer attached to the bottom of the element. */
gmp-place-details-compact::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 16px solid transparent;
  border-right: 16px solid transparent;
  border-top: 20px solid var(--gmp-mat-color-surface, light-dark(white, black));
}

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 id="map-container">
      <gmp-basic-place-autocomplete></gmp-basic-place-autocomplete>
      <gmp-place-details-compact orientation="horizontal">
        <gmp-place-details-place-request></gmp-place-details-place-request>
        <gmp-place-all-content></gmp-place-all-content>
      </gmp-place-details-compact>
      <gmp-map zoom="14" map-id="DEMO_MAP_ID">
         <gmp-advanced-marker></gmp-advanced-marker> 
      </gmp-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>

Dùng thử mẫu