Place Autocomplete

簡介

「自動完成」是 Maps JavaScript API Places Library 的功能。您可以運用這項功能,在應用程式中提供 Google 地圖搜尋欄位的預先輸入搜尋功能。「自動完成」服務可比對完整字詞和子字串,解析地點名稱、地址和 Plus Codes。因此,應用程式可在使用者輸入內容時傳送查詢,即時提供地點預測結果。

開始使用

請先在 Google Cloud 控制台中,確認您為 Maps JavaScript API 設定的專案已啟用 Places API,然後再開始使用 Maps JavaScript API Places Library。

如要查看已啟用的 API 清單,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台
  2. 按一下「選取專案」按鈕,選取同一個針對 Maps JavaScript API 設定的專案,然後點選「開啟」
  3. 在「資訊主頁」的 API 清單中,找出 Places API
  4. 如果在清單中看到該 API,就表示一切就緒。如果「沒有」看到這個 API,請按照下列步驟進行啟用:
    1. 選取頁面頂端的「啟用 API」,即會顯示「程式庫」分頁。或者,您也可以從左側選單中選取「程式庫」
    2. 搜尋「Places API」,然後從結果清單中選取該 API。
    3. 選取「啟用」。這個程序完成後,「資訊主頁」的 API 清單就會顯示「Places API」

載入程式庫

地點介面集服務是獨立程式庫,不包含在主要的 Maps JavaScript API 程式碼。如要使用這個程式庫中的功能,您必須先在 Maps API Bootstrap 網址中使用 libraries 參數載入程式庫:

<script async
    src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap">
</script>

詳情請參閱「程式庫總覽」一文。

類別摘要

API 提供兩種 Autocomplete 小工具,您可以分別透過 AutocompleteSearchBox 類別新增。此外,您可以使用 AutocompleteService 類別,透過程式輔助方式擷取自動完成結果 (請參閱 Maps JavaScript API 參考資料:AutocompleteService 類別)。

以下簡要說明可用的類別:

  • Autocomplete 會在您的網頁中加入一個文字輸入欄位,並監控該欄位是否有輸入的字元。使用者輸入文字時,自動完成功能會以下拉式選單的形式傳回地點預測結果。如果使用者選取清單中的地點,該地點資訊就會傳回給自動完成物件供應用程式擷取。詳情請參閱下文
    提供自動完成功能的文字欄位,以及使用者輸入搜尋查詢時顯示的地點預測結果選單。
    圖 1:自動完成文字欄位和選單
    完成的地址表單。
    圖 2:完成的地址表單
  • SearchBox 會在您的網頁中加入一個文字輸入欄位,方法與 Autocomplete 大致相同,但有以下差異:
    • 主要差異在於選單中顯示的結果。SearchBox 提供更廣泛的預測結果清單,其中可能含有地點 (依 Places API 定義) 和建議搜尋字詞。舉例來說,如果使用者輸入「披薩台」,選單可能就會提供「披薩台北」這個詞組及許多披薩店的名稱。
    • SearchBox 提供的搜尋範圍限制選項比 Autocomplete 少。如果是前者,您可以將搜尋範圍調為優先考慮指定的 LatLngBounds。如果是後者,您可以將搜尋範圍限制在特定國家/地區和特定地點類型,並設定邊界。詳情請參閱下文
    完成的地址表單。
    圖 3:搜尋框顯示搜尋字詞和地點預測結果。
    詳情請參閱下文
  • 您可以建立 AutocompleteService 物件,透過程式輔助方式擷取預測結果。呼叫 getPlacePredictions() 可擷取相符地點,呼叫 getQueryPredictions() 則可擷取相符的地點和建議搜尋字詞。注意:AutocompleteService 不會新增任何 UI 控制項。反之,上述方法會傳回預測結果物件的陣列。每個預測結果物件都包含預測結果文字、參考資訊,以及該結果與使用者輸入內容相符程度的詳細資料。詳情請參閱下文

新增 Autocomplete 小工具

Autocomplete 小工具會在您的網頁上建立文字輸入欄位、在使用者介面選單中提供地點預測結果,以及傳回 Place Details 來回應 getPlace() 要求。選單中的每個項目都對應至單一地點 (如 Places API 所定義)。

Autocomplete 建構函式會採用兩個引數:

  • text 類型的 HTML input 元素。自動完成服務會監控這個輸入欄位,並將結果附加到這裡。
  • 自選的 AutocompleteOptions 引數,可包含以下屬性:
    • 資料 fields 陣列,要加進使用者所選 PlaceResultPlace Details 回應中。如未設定屬性,或已傳入 ['ALL'],系統會傳回所有可用的欄位並據此收費 (不適用於實際工作環境部署作業)。如需欄位清單,請參閱 PlaceResult
    • types 陣列,用於指定明確類型或類型集合,如支援類型中所列。如果沒有指定類型,系統就會傳回所有類型。
    • boundsgoogle.maps.LatLngBounds 物件,用於指定地點搜尋範圍。結果可能會優先 (但不限於) 顯示這些邊界內的地點。
    • strictBoundsboolean,用於指定 API 是否只能傳回完全位於指定 bounds 所定義區域內的地點。無論是否與使用者的輸入內容相符,API 都不會傳回這個區域以外的結果。
    • componentRestrictions 可用於將結果範圍限制在特定群組。您目前可以使用 componentRestrictions 按國家/地區 (最多 5 個) 進行篩選。傳遞國家/地區時,請務必使用雙字元 ISO 3166-1 Alpha-2 相容國家/地區代碼。如有多個國家/地區,則必須以國家/地區代碼清單的形式傳遞。

      注意:如果使用國家/地區代碼時收到非預期的結果,請確認您使用的代碼是否包含所需的國家/地區、附屬領土和特殊地理區域。如要取得代碼相關資訊,您可以查看維基百科的 ISO 3166 國家/地區代碼清單ISO 線上瀏覽平台

    • placeIdOnly 可用於指示 Autocomplete 小工具只擷取地點 ID。針對 Autocomplete 物件呼叫 getPlace() 時,提供的 PlaceResult 只會設定 place idtypesname 屬性。傳回的地點 ID 可搭配以下服務呼叫使用:Places、Geocoding、Directions 或 Distance Matrix。

限制自動預測結果

根據預設,Place Autocomplete 會顯示所有地點類型 (優先顯示使用者所在位置附近的預測結果),並擷取使用者所選地點的所有可用資料欄位。設定 Place Autocomplete 選項,即可根據您的使用情形顯示更相關的預測結果。

在建構時設定選項

Autocomplete 建構函式接受 AutocompleteOptions 參數,可在建立小工具時設定限制。以下範例將設定 boundscomponentRestrictionstypes 選項,要求 establishment 類型的地點,且除了優先顯示特定地理區域內的地點,還會將預測結果限制為美國境內的地點。設定 fields 選項,即可指定要傳回哪些有關使用者所選地點的資訊。

呼叫 setOptions() 即可變更現有小工具的選項值。

TypeScript

const center = { lat: 50.064192, lng: -130.605469 };
// Create a bounding box with sides ~10km away from the center point
const defaultBounds = {
  north: center.lat + 0.1,
  south: center.lat - 0.1,
  east: center.lng + 0.1,
  west: center.lng - 0.1,
};
const input = document.getElementById("pac-input") as HTMLInputElement;
const options = {
  bounds: defaultBounds,
  componentRestrictions: { country: "us" },
  fields: ["address_components", "geometry", "icon", "name"],
  strictBounds: false,
  types: ["establishment"],
};

const autocomplete = new google.maps.places.Autocomplete(input, options);

JavaScript

const center = { lat: 50.064192, lng: -130.605469 };
// Create a bounding box with sides ~10km away from the center point
const defaultBounds = {
  north: center.lat + 0.1,
  south: center.lat - 0.1,
  east: center.lng + 0.1,
  west: center.lng - 0.1,
};
const input = document.getElementById("pac-input");
const options = {
  bounds: defaultBounds,
  componentRestrictions: { country: "us" },
  fields: ["address_components", "geometry", "icon", "name"],
  strictBounds: false,
  types: ["establishment"],
};
const autocomplete = new google.maps.places.Autocomplete(input, options);

指定資料欄位

指定資料欄位,避免支付非必要的地點資料 SKU 費用。在傳遞至小工具建構函式的 AutocompleteOptions 中加入 fields 屬性 (如上例所示),或是針對現有的 Autocomplete 物件呼叫 setFields()

autocomplete.setFields(["place_id", "geometry", "name"]);

定義自動完成功能的自訂調整設定和搜尋區域邊界

您可透過以下方式,針對自動完成結果進行自訂調整,優先顯示某個大概位置或區域:

  • 在建立 Autocomplete 物件時設定邊界。
  • 變更現有 Autocomplete 的邊界。
  • 將邊界設為地圖的可視區域。
  • 將搜尋範圍限制在邊界內。
  • 將搜尋範圍限制在特定國家/地區內。

上例說明如何在建立時設定邊界,下例則示範其他自訂調整技巧。

變更現有 Autocomplete 的邊界

呼叫 setBounds() 可將現有 Autocomplete 的搜尋區域變更為矩形邊界。

TypeScript

const southwest = { lat: 5.6108, lng: 136.589326 };
const northeast = { lat: 61.179287, lng: 2.64325 };
const newBounds = new google.maps.LatLngBounds(southwest, northeast);

autocomplete.setBounds(newBounds);

JavaScript

const southwest = { lat: 5.6108, lng: 136.589326 };
const northeast = { lat: 61.179287, lng: 2.64325 };
const newBounds = new google.maps.LatLngBounds(southwest, northeast);

autocomplete.setBounds(newBounds);
將邊界設為地圖的可視區域

使用 bindTo() 可針對地圖的可視區域調整結果 (無論該可視區域是否變更)。

TypeScript

autocomplete.bindTo("bounds", map);

JavaScript

autocomplete.bindTo("bounds", map);

使用 unbind() 可將自動預測結果與地圖可視區域解除繫結。

TypeScript

autocomplete.unbind("bounds");
autocomplete.setBounds({ east: 180, west: -180, north: 90, south: -90 });

JavaScript

autocomplete.unbind("bounds");
autocomplete.setBounds({ east: 180, west: -180, north: 90, south: -90 });

查看範例

將搜尋範圍限制在目前邊界內

設定 strictBounds 選項可將結果範圍限制在目前的邊界內 (無論是地圖可視區域的邊界或矩形邊界)。

autocomplete.setOptions({ strictBounds: true });
將預測結果範圍限制在特定國家/地區內

使用 componentRestrictions 選項或呼叫 setComponentRestrictions(),可將自動完成搜尋範圍限制在特定的國家/地區 (最多五個) 組合內。

TypeScript

autocomplete.setComponentRestrictions({
  country: ["us", "pr", "vi", "gu", "mp"],
});

JavaScript

autocomplete.setComponentRestrictions({
  country: ["us", "pr", "vi", "gu", "mp"],
});

查看範例

限制地點類型

使用 types 選項或呼叫 setTypes(),可將預測結果限制為特定類型。這項限制會指定類型或類型集合,如「地點類型」一文所列。如未指定限制,則會傳回所有類型。

對於 types 選項的值或傳遞至 setTypes() 的值,您可以指定下列其中一項:

  • 一個陣列,包含「地點類型」一文表 1表 2 中的值 (最多五個),例如:

    types: ['hospital', 'pharmacy', 'bakery', 'country']

    或:

    autocomplete.setTypes(['hospital', 'pharmacy', 'bakery', 'country']);
  • 地點類型」一文表 3 中的任一篩選器。您只能指定表 3 中的一個值。

如有下列情況,要求就會遭拒:

  • 指定超過五個類型。
  • 指定任何無法辨識的類型。
  • 表 1表 2 中的任何類型,與表 3 中的任何篩選器搭配使用。

Place Autocomplete 範例顯示不同地點類型之間的預測結果差異。

前往示範

取得地點資訊

當使用者從附加至自動完成文字欄位的預測結果選取地點,服務就會觸發 place_changed 事件。如要取得 Place Details,請按照下列步驟操作:

  1. place_changed 事件建立事件處理常式,並針對 Autocomplete 物件呼叫 addListener(),新增處理常式。
  2. 針對 Autocomplete 物件呼叫 Autocomplete.getPlace() 擷取 PlaceResult 物件,接著您就能使用該物件取得更多有關已選地點的資訊。

根據預設,當使用者選取地點,自動完成功能會傳回已選地點的所有可用資料欄位並據此收費。使用 Autocomplete.setFields() 即可指定要傳回的地點資料欄位。進一步瞭解 PlaceResult 物件,包括可要求的地點資料欄位清單。為避免支付不必要的資料費用,請務必使用 Autocomplete.setFields(),僅指定要使用的地點資料。

name 屬性包含 Places Autocomplete 預測結果中的 description。如要進一步瞭解 description,請參閱 Places Autocomplete 說明文件

如果是地址表單,建議您取得結構化格式的地址。如要傳回已選地點的結構化地址,請呼叫 Autocomplete.setFields() 並指定 address_components 欄位。

下例會使用自動完成功能填寫地址表單欄位。

TypeScript

function fillInAddress() {
  // Get the place details from the autocomplete object.
  const place = autocomplete.getPlace();
  let address1 = "";
  let postcode = "";

  // Get each component of the address from the place details,
  // and then fill-in the corresponding field on the form.
  // place.address_components are google.maps.GeocoderAddressComponent objects
  // which are documented at http://goo.gle/3l5i5Mr
  for (const component of place.address_components as google.maps.GeocoderAddressComponent[]) {
    // @ts-ignore remove once typings fixed
    const componentType = component.types[0];

    switch (componentType) {
      case "street_number": {
        address1 = `${component.long_name} ${address1}`;
        break;
      }

      case "route": {
        address1 += component.short_name;
        break;
      }

      case "postal_code": {
        postcode = `${component.long_name}${postcode}`;
        break;
      }

      case "postal_code_suffix": {
        postcode = `${postcode}-${component.long_name}`;
        break;
      }

      case "locality":
        (document.querySelector("#locality") as HTMLInputElement).value =
          component.long_name;
        break;

      case "administrative_area_level_1": {
        (document.querySelector("#state") as HTMLInputElement).value =
          component.short_name;
        break;
      }

      case "country":
        (document.querySelector("#country") as HTMLInputElement).value =
          component.long_name;
        break;
    }
  }

  address1Field.value = address1;
  postalField.value = postcode;

  // After filling the form with address components from the Autocomplete
  // prediction, set cursor focus on the second address line to encourage
  // entry of subpremise information such as apartment, unit, or floor number.
  address2Field.focus();
}

JavaScript

function fillInAddress() {
  // Get the place details from the autocomplete object.
  const place = autocomplete.getPlace();
  let address1 = "";
  let postcode = "";

  // Get each component of the address from the place details,
  // and then fill-in the corresponding field on the form.
  // place.address_components are google.maps.GeocoderAddressComponent objects
  // which are documented at http://goo.gle/3l5i5Mr
  for (const component of place.address_components) {
    // @ts-ignore remove once typings fixed
    const componentType = component.types[0];

    switch (componentType) {
      case "street_number": {
        address1 = `${component.long_name} ${address1}`;
        break;
      }

      case "route": {
        address1 += component.short_name;
        break;
      }

      case "postal_code": {
        postcode = `${component.long_name}${postcode}`;
        break;
      }

      case "postal_code_suffix": {
        postcode = `${postcode}-${component.long_name}`;
        break;
      }
      case "locality":
        document.querySelector("#locality").value = component.long_name;
        break;
      case "administrative_area_level_1": {
        document.querySelector("#state").value = component.short_name;
        break;
      }
      case "country":
        document.querySelector("#country").value = component.long_name;
        break;
    }
  }

  address1Field.value = address1;
  postalField.value = postcode;
  // After filling the form with address components from the Autocomplete
  // prediction, set cursor focus on the second address line to encourage
  // entry of subpremise information such as apartment, unit, or floor number.
  address2Field.focus();
}

window.initAutocomplete = initAutocomplete;

查看範例

自訂預留位置文字

根據預設,自動完成服務所建立的文字欄位會包含標準預留位置文字。如要修改文字,請針對 input 元素設定 placeholder 屬性:

<input id="searchTextField" type="text" size="50" placeholder="Anything you want!">

注意:預設的預留位置文字會自動本地化。如果您要自行指定預留位置值,就必須處理該值在應用程式中的本地化作業。如想瞭解 Google Maps JavaScript API 如何選擇要使用的語言,請參閱本地化相關說明文件。

如要自訂小工具外觀,請參閱「設定 Autocomplete 和 SearchBox 小工具的樣式」一節。

SearchBox 可讓使用者使用文字進行地理位置搜尋,例如「台北披薩」或「石牌路附近的鞋店」。您可以將 SearchBox 附加至文字欄位,這樣當使用者輸入文字時,服務就會以下拉式選單的形式傳回預測結果。

SearchBox 提供更廣泛的預測結果清單,其中可能含有地點 (依 Places API 定義) 和建議搜尋字詞。舉例來說,如果使用者輸入「披薩台」,選單可能就會含有「披薩台北」這個詞組,以及各式各樣的披薩店名稱。使用者選取清單中的地點時,系統就會將地點資訊傳回給 SearchBox 物件,以供應用程式擷取。

SearchBox 建構函式會採用兩個引數:

  • text 類型的 HTML input 元素。SearchBox 服務會監控並將結果附加到這個輸入欄位。
  • options 引數,可包含 bounds 屬性:boundsgoogle.maps.LatLngBounds 物件,用於指定地點搜尋範圍。結果可能會優先 (但不限於) 顯示這些邊界內的地點。

以下程式碼會使用 bounds 參數,針對特定地理區域 (透過經緯度座標指定) 內的地點調整結果。

var defaultBounds = new google.maps.LatLngBounds(
  new google.maps.LatLng(-33.8902, 151.1759),
  new google.maps.LatLng(-33.8474, 151.2631));

var input = document.getElementById('searchTextField');

var searchBox = new google.maps.places.SearchBox(input, {
  bounds: defaultBounds
});

變更 SearchBox 的搜尋區域

如要變更現有 SearchBox 的搜尋區域,請針對 SearchBox 物件呼叫 setBounds(),並傳遞相關的 LatLngBounds 物件。

查看範例

取得地點資訊

當使用者從附加至搜尋框的預測結果選取項目,這項服務就會觸發 places_changed 事件。您可以針對 SearchBox 物件呼叫 getPlaces(),擷取含有多筆預測結果的陣列,每筆預測結果都是 PlaceResult 物件。

如要進一步瞭解 PlaceResult 物件,請參閱 Place Details 結果相關說明文件。

TypeScript

// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener("places_changed", () => {
  const places = searchBox.getPlaces();

  if (places.length == 0) {
    return;
  }

  // Clear out the old markers.
  markers.forEach((marker) => {
    marker.setMap(null);
  });
  markers = [];

  // For each place, get the icon, name and location.
  const bounds = new google.maps.LatLngBounds();

  places.forEach((place) => {
    if (!place.geometry || !place.geometry.location) {
      console.log("Returned place contains no geometry");
      return;
    }

    const icon = {
      url: place.icon as string,
      size: new google.maps.Size(71, 71),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(17, 34),
      scaledSize: new google.maps.Size(25, 25),
    };

    // Create a marker for each place.
    markers.push(
      new google.maps.Marker({
        map,
        icon,
        title: place.name,
        position: place.geometry.location,
      })
    );

    if (place.geometry.viewport) {
      // Only geocodes have viewport.
      bounds.union(place.geometry.viewport);
    } else {
      bounds.extend(place.geometry.location);
    }
  });
  map.fitBounds(bounds);
});

JavaScript

// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener("places_changed", () => {
  const places = searchBox.getPlaces();

  if (places.length == 0) {
    return;
  }

  // Clear out the old markers.
  markers.forEach((marker) => {
    marker.setMap(null);
  });
  markers = [];

  // For each place, get the icon, name and location.
  const bounds = new google.maps.LatLngBounds();

  places.forEach((place) => {
    if (!place.geometry || !place.geometry.location) {
      console.log("Returned place contains no geometry");
      return;
    }

    const icon = {
      url: place.icon,
      size: new google.maps.Size(71, 71),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(17, 34),
      scaledSize: new google.maps.Size(25, 25),
    };

    // Create a marker for each place.
    markers.push(
      new google.maps.Marker({
        map,
        icon,
        title: place.name,
        position: place.geometry.location,
      })
    );
    if (place.geometry.viewport) {
      // Only geocodes have viewport.
      bounds.union(place.geometry.viewport);
    } else {
      bounds.extend(place.geometry.location);
    }
  });
  map.fitBounds(bounds);
});

查看範例

如要自訂小工具外觀,請參閱「設定 Autocomplete 和 SearchBox 小工具的樣式」一節。

透過程式輔助方式擷取 Place Autocomplete 服務預測結果

如要透過程式輔助方式擷取預測結果,您可以使用 AutocompleteService 類別。AutocompleteService 不會新增任何 UI 控制項,而是傳回預測結果物件的陣列。每個預測結果物件都包含預測結果文字、參考資訊,以及該結果與使用者輸入內容相符程度的詳細資料。與上述 AutocompleteSearchBox 提供的控制功能相比,運用這項方法可以更有效地控制使用者介面。

AutocompleteService 提供下列方法:

  • getPlacePredictions() 會傳回地點預測結果。注意:如 Places API 所定義,「地點」可以是建築物、地理位置或重要搜尋點。
  • getQueryPredictions() 會傳回更廣泛的預測結果清單,其中可能含有地點 (依 Places API 定義) 和建議搜尋字詞。舉例來說,如果使用者輸入「披薩台」,選單可能就會提供「披薩台北」這個詞組及許多披薩店的名稱。

上述兩種方法都會傳回預測結果物件的陣列,格式如下:

  • description 是相符的預測結果。
  • distance_meters 是地點與指定 AutocompletionRequest.origin 的距離 (以公尺為單位)。
  • matched_substrings 在說明中包含一組子字串,這些字串與使用者輸入內容中的元素相符。如果您想在應用程式中標明這些子字串,就很適合採用這項做法。在許多情況下,查詢會以說明欄位的子字串形式顯示。
    • length 是子字串的長度。
    • offset 是從說明字串開頭 (相符子字串顯示位置) 算起的字元偏移值。
  • place_id 是用來識別特定地點的文字 ID。如要擷取地點資訊,請在 Place Details 要求placeId 欄位中傳遞這個 ID。進一步瞭解如何使用地點 ID 參照地點
  • terms 是包含查詢元素的陣列。地點的每個元素通常會構成地址的一部分。
    • offset 是從說明字串開頭 (相符子字串顯示位置) 算起的字元偏移值。
    • value 是相符的字詞。

下例會執行查詢「附近披薩」一詞的預測結果要求,並在清單中顯示結果。

TypeScript

// This example retrieves autocomplete predictions programmatically from the
// autocomplete service, and displays them as an HTML list.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initService(): void {
  const displaySuggestions = function (
    predictions: google.maps.places.QueryAutocompletePrediction[] | null,
    status: google.maps.places.PlacesServiceStatus
  ) {
    if (status != google.maps.places.PlacesServiceStatus.OK || !predictions) {
      alert(status);
      return;
    }

    predictions.forEach((prediction) => {
      const li = document.createElement("li");

      li.appendChild(document.createTextNode(prediction.description));
      (document.getElementById("results") as HTMLUListElement).appendChild(li);
    });
  };

  const service = new google.maps.places.AutocompleteService();

  service.getQueryPredictions({ input: "pizza near Syd" }, displaySuggestions);
}

declare global {
  interface Window {
    initService: () => void;
  }
}
window.initService = initService;

JavaScript

// This example retrieves autocomplete predictions programmatically from the
// autocomplete service, and displays them as an HTML list.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initService() {
  const displaySuggestions = function (predictions, status) {
    if (status != google.maps.places.PlacesServiceStatus.OK || !predictions) {
      alert(status);
      return;
    }

    predictions.forEach((prediction) => {
      const li = document.createElement("li");

      li.appendChild(document.createTextNode(prediction.description));
      document.getElementById("results").appendChild(li);
    });
  };

  const service = new google.maps.places.AutocompleteService();

  service.getQueryPredictions({ input: "pizza near Syd" }, displaySuggestions);
}

window.initService = initService;

CSS

HTML

<html>
  <head>
    <title>Retrieving Autocomplete Predictions</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <p>Query suggestions for 'pizza near Syd':</p>
    <ul id="results"></ul>
    <!-- Replace Powered By Google image src with self hosted image. https://developers.google.com/maps/documentation/places/web-service/policies#other_attribution_requirements -->
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!--
      The `defer` attribute causes the callback to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initService&libraries=places&v=weekly"
      defer
    ></script>
  </body>
</html>

試用範例

查看範例

工作階段符記

AutocompleteService.getPlacePredictions() 會使用工作階段符記,將自動完成要求分類以用於計費。工作階段符記會將使用者自動完成搜尋的查詢和選取階段歸入不同的工作階段,以用於計費。工作階段是從使用者輸入查詢時開始,到使用者選取地點時結束。在每個工作階段中,使用者可以輸入多筆查詢,最終選擇一個地點。工作階段結束後,符記就會失效。您的應用程式必須為每個工作階段產生新的符記。建議您在所有自動完成工作階段使用工作階段符記。如果省略 sessionToken 參數或重複使用工作階段符記,系統會視為未提供工作階段符記,並針對工作階段收費 (每個要求分別收費)。

您可以使用同一個工作階段符記,針對呼叫 AutocompleteService.getPlacePredictions() 取得的地點提出一項 Place Details 要求。在這種情況下,自動完成要求會與 Place Details 要求合併,而呼叫會按照一般 Place Details 要求收費。系統不會針對自動完成要求收費。

請務必針對每個新的工作階段傳遞不重複的工作階段符記。如果多個自動完成工作階段都使用同一個符記,這些自動完成工作階段就會失效,而系統會使用 Autocomplete Per Request SKU,針對無效工作階段中的所有自動完成要求分別收費。進一步瞭解工作階段符記

下例說明如何建立工作階段符記,然後在 AutocompleteService 中傳遞 (為求精簡會省略 displaySuggestions() 函式):

// Create a new session token.
var sessionToken = new google.maps.places.AutocompleteSessionToken();

// Pass the token to the autocomplete service.
var autocompleteService = new google.maps.places.AutocompleteService();
autocompleteService.getPlacePredictions({
  input: 'pizza near Syd',
  sessionToken: sessionToken
},
displaySuggestions);

請務必針對每個新的工作階段傳遞不重複的工作階段符記。如果多個工作階段使用同一個符記,則每個要求會分別計費。

進一步瞭解工作階段符記

設定 Autocomplete 和 SearchBox 小工具的樣式

根據預設,AutocompleteSearchBox 提供的 UI 元素會經過樣式設定再加進 Google 地圖。您可以根據自己的網站調整樣式。下列 CSS 類別可供您使用,且同時適用於 AutocompleteSearchBox 小工具。

Autocomplete 和 SearchBox 小工具適用的 CSS 類別圖解說明
Autocomplete 和 SearchBox 小工具適用的 CSS 類別
CSS 類別 說明
pac-container 視覺元素,包含 Place Autocomplete 服務傳回的預測結果清單。這份清單會以下拉式清單的形式,顯示在 AutocompleteSearchBox 小工具下方。
pac-icon 顯示在預測結果清單中每個項目左側的圖示。
pac-item AutocompleteSearchBox 小工具預測結果清單中的項目。
pac-item:hover 使用者滑鼠游標懸停的項目。
pac-item-selected 使用者透過鍵盤選取的項目。注意:已選取的項目將歸入這個類別和 pac-item 類別。
pac-item-query pac-item 內的範圍,是預測結果的主要部分。如果是地理位置,其中會包含地點名稱 (例如「淡水」),或街道名稱及門牌號碼 (例如「中正路 3 號」)。如果是文字搜尋 (例如「台北披薩」),其中會包含整段查詢文字。pac-item-query 的預設顏色為黑色。如果 pac-item 中有任何額外文字,則會位於 pac-item-query 之外,並沿用 pac-item 的樣式。在預設情況下會以灰色顯示。這段額外文字通常是地址。
pac-matched 傳回的預測結果中,與使用者輸入內容相符的部分。根據預設,這段相符文字會以粗體強調。請注意,相符文字可能會在 pac-item 內的任何位置,不一定是 pac-item-query 的一部分,也可能部分包含在 pac-item-query 中,以及部分包含在 pac-item 的其餘文字中。

Place Autocomplete 最佳化

本節將說明最佳做法,協助您充分運用 Place Autocomplete 服務。

以下列出幾項一般準則:

  • 如要開發有效的使用者介面,最快的方法就是使用 Maps JavaScript API Autocomplete 小工具、Places SDK for Android Autocomplete 小工具,或 Places SDK for iOS Autocomplete UI 控制項
  • 從一開始就嘗試瞭解 Place Autocomplete 的必要資料欄位
  • 「位置自訂調整」和「位置限制」為自選欄位,但可能會對自動完成效能產生重大影響。
  • 使用錯誤處理機制,可以減輕 API 傳回錯誤時對應用程式效能造成的影響。
  • 確保應用程式能處理未選取任何項目的情況,以便使用者繼續操作。

費用最佳化最佳做法

基本費用最佳化

為了讓 Place Autocomplete 服務費用發揮最大效益,請使用 Place Details 和 Place Autocomplete 小工具中的欄位遮罩,只傳回所需的地點資料欄位

進階費用最佳化

建議您透過程式輔助方式導入 Place Autocomplete,採用按請求計價,並要求已選地點 (而非 Place Details) 的相關 Geocoding API 結果。如果同時符合以下兩項條件,搭配 Geocoding API 使用「按要求」計價會比使用「按工作階段」(以工作階段為準) 計價更具成本效益:

  • 如果您只需要針對使用者選取的地點取得經緯度或地址,透過 Geocoding API 擷取這項資訊,支付的費用會比使用 Place Details 呼叫更低。
  • 如果使用者在平均四次以內的自動預測結果要求選取了自動預測結果,則「按要求」計價可能會比「按工作階段」計價更符合成本效益。
如要瞭解如何選取符合需求的 Place Autocomplete 導入方式,請回答下列問題,並選取對應的分頁標籤。

除了所選預測結果的地址和經緯度,應用程式是否需要任何其他資訊?

是,需要更多詳細資料

搭配 Place Details 使用以工作階段為準的 Place Autocomplete。
您的應用程式會要求 Place Details (例如地點名稱、商家狀態或營業時間),因此在導入 Place Autocomplete 時,建議使用工作階段符記 (透過程式輔助方式,或是內建於 JavaScriptAndroidiOS 小工具),總費用為每個工作階段 $0.017 美元,再加上適用的地點資料 SKU (視您要求的地點資料欄位而定)1

透過小工具導入
JavaScriptAndroidiOS 小工具自動內建工作階段管理功能,其中包含對已選取的預測結果提出的 Place Autocomplete 要求和 Place Details 要求。請務必指定 fields 參數,確保您只要求所需的地點資料欄位

透過程式輔助方式導入
搭配 Place Autocomplete 要求使用工作階段符記。要求所選預測結果的相關 Place Details 時,請加入下列參數:

  1. Place Autocomplete 回應中的地點 ID
  2. Place Autocomplete 要求中使用的工作階段符記
  3. 指定所需地點資料欄位fields 參數

否,只需要地址和位置資訊

對您的應用程式而言,Geocoding API 可能比 Place Details 更符合成本效益,視 Place Autocomplete 使用效能而定。每個應用程式的自動完成效率各不相同,可能取決於使用者輸入的內容、使用應用程式的位置,以及是否採用效能最佳化最佳做法

為了找出以下問題的解答,請分析使用者在應用程式中選取 Place Autocomplete 預測結果前,平均輸入的字元數量。

使用者是否會在平均四次以內的要求中選取 Place Autocomplete 預測結果?

透過程式輔助方式導入 Place Autocomplete,但不使用工作階段符記,並針對已選取的地點預測結果呼叫 Geocoding API。
Geocoding API 提供地址和經緯度座標,收費為每次要求 $0.005 美元。提出四次 Place Autocomplete - Per Request 要求的費用為 $0.01132 美元,因此如果將四次要求加上所選地點預測結果的相關 Geocoding API 呼叫,總費用就會是 $0.01632 美元,低於自動完成功能「按工作階段」計價的每個工作階段 $0.017 美元1

建議您採用效能最佳做法,讓使用者以更少的字元找到需要的預測結果。

搭配 Place Details 使用以工作階段為準的 Place Autocomplete。
您預期使用者在選取 Place Autocomplete 預測結果前提出的平均要求數量,會超過「按工作階段」計價的費用,因此在導入 Place Autocomplete 時,建議針對 Place Autocomplete 要求和相關聯的 Place Details 要求都使用工作階段符記,總費用為每個工作階段 $0.017 美元1

透過小工具導入
JavaScriptAndroidiOS 小工具自動內建工作階段管理功能,其中包含對已選取的預測結果提出的 Place Autocomplete 要求和 Place Details 要求。請務必指定 fields 參數,確保只要求需要的 Basic Data 欄位。

透過程式輔助方式導入
搭配 Place Autocomplete 要求使用工作階段符記。要求所選預測結果的相關 Place Details 時,請加入下列參數:

  1. Place Autocomplete 回應中的地點 ID
  2. Place Autocomplete 要求中使用的工作階段符記
  3. 指定地址和幾何圖形等 Basic Data 欄位的 fields 參數

考慮延後 Place Autocomplete 要求
您可以運用一些策略,例如將 Place Autocomplete 要求延後到使用者輸入三或四個字元時再開始,藉此減少應用程式提出要求數量。舉例來說,如果您是在使用者輸入第三個字元「之後」才針對每個字元提出 Place Autocomplete 要求,那麼當使用者在輸入七個字元後,選取您透過單次 Geocoding API 要求帶出的一筆預測結果,總費用就是 $0.01632 美元 (4 * $0.00283 Autocomplete Per Request + $0.005 美元 Geocoding)1

如果延後要求可以讓平均程式輔助要求少於四次,您可以按照使用 Geocoding API 提高 Place Autocomplete 效能的指南操作。請注意,如果使用者希望每輸入一個字就能看到預測結果,可能就會將延後要求視為時間上的延遲。

建議您採用效能最佳做法,讓使用者以更少的字元找到需要的預測結果。


  1. 這裡列出的費用是以美元計算。如需完整計價資訊,請參閱「Google 地圖平台計費方式」頁面。

效能最佳做法

以下準則說明如何將 Place Autocomplete 效能最佳化:

  • 針對導入的 Place Autocomplete 加入國家/地區限制、位置自訂調整和 (適用於程式輔助導入) 語言偏好設定。小工具會從使用者的瀏覽器或行動裝置選擇語言偏好設定,因此不需要設定語言偏好。
  • 如果 Place Autocomplete 附帶地圖,您就可以根據地圖可視區域進行位置自訂調整。
  • 如果使用者沒有選擇任何自動預測結果 (通常是因為這些預測結果並非他們想要的地址),您可以重複使用原始使用者輸入內容,嘗試取得更相關的結果:
    • 如果您預期使用者只會輸入地址資訊,請在 Geocoding API 呼叫中重複使用原始使用者輸入內容。
    • 如果您預期使用者會依名稱或地址查詢某個地點,請使用「Find Place」要求。如果希望將結果範圍限制在特定區域,請使用位置自訂調整
    適合改回使用 Geocoding API 的其他情況如下:
    • 使用者輸入的次要場所地址,位於 Place Autocomplete 未能完整提供次要場所地址支援的國家/地區 (例如捷克、愛沙尼亞和立陶宛)。例如,捷克地址「Stroupežnického 3191/17, Praha」在 Place Autocomplete 中會產生不完整的預測結果。
    • 使用者輸入的地址含有路段前置字元,例如紐約的「23-30 29th St, Queens」或夏威夷考艾島的「47-380 Kamehameha Hwy, Kaneohe」。

用量限制和政策

配額

如需配額與定價資訊,請參閱 Places API 的「用量與計費」說明文件

政策

使用 Maps JavaScript API Places Library 時,必須遵守 Places API 適用的現行政策