迁移到新版地点自动补全

欧洲经济区 (EEA) 开发者

地点自动补全是 Maps JavaScript API 中地点库的一项功能。借助自动补全,您可以让自己的应用具有 Google 地图搜索字段的“即输即找”功能。

本页介绍了旧版和新版地点自动补全功能之间的区别。在这两个版本中,集成自动补全功能一般有两种方式:

自动补全编程接口

下表列出了地点自动补全服务(旧版)自动补全数据 API(新版)在以编程方式使用地点自动补全功能方面的一些主要区别:

PlacesService(旧版) Place(新)
地点自动补全服务参考文档 自动补全数据(新)参考
AutocompletionRequest AutocompleteRequest
AutocompleteService.getPlacePredictions AutocompleteSuggestion.fetchAutocompleteSuggestions
AutocompletePrediction PlacePrediction
方法需要使用回调来处理结果对象和 PlacesServiceStatus 响应。 使用 Promise,并以异步方式运行。
方法需要进行 PlacesServiceStatus 检查。 无需进行状态检查,可以使用标准错误处理。
位置数据字段是在创建 Autocomplete 实例时作为选项设置的。 地点数据字段会在稍后调用 fetchFields() 时设置。
支持查询预测(仅限 SearchBox)。 Autocomplete 类中没有查询预测。
仅限于一组固定的地点类型地点数据字段 可访问更多地点类型地点数据字段

以下内容同时适用于旧版和新版 Autocomplete API:

代码比较(程序化)

本部分将比较自动补全的代码,以说明 Places 服务与 Place 类(针对程序化接口)之间的区别。

检索自动补全预测结果(旧版)

借助旧版 Places 服务,您可以以编程方式检索自动补全预测结果,从而比 Autocomplete 类更灵活地控制用户界面。在以下示例中,系统针对“par”发出单个请求,其中 AutocompletionRequest 包含输入值和一组用于对预测进行偏置的界限。此示例返回 AutocompletePrediction 实例的列表,并显示每个实例的说明。示例函数还会创建会话令牌并将其应用于请求。

function init() {
  const placeInfo = document.getElementById("prediction");
  const service = new google.maps.places.AutocompleteService();
  const placesService = new google.maps.places.PlacesService(placeInfo);
  var sessionToken = new google.maps.places.AutocompleteSessionToken();

  // Define request options.
  let request = {
    input: "par",
    sessionToken: sessionToken,
    bounds: {
      west: -122.44,
      north: 37.8,
      east: -122.39,
      south: 37.78,
    },
  }

  // Display the query string.
  const title = document.getElementById("title");
  title.appendChild(
    document.createTextNode('Place predictions for "' + request.input + '":'),
  );

  // Perform the query and display the results.
  const displaySuggestions = function (predictions, status) {
    // Check the status of the Places Service.
    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 placeRequest = {
      placeId: predictions[0].place_id,
      fields: ["name", "formatted_address"],
    };

    placesService.getDetails(placeRequest, (place, status) => {
      if (status == google.maps.places.PlacesServiceStatus.OK && place) {
        placeInfo.textContent = `
          First predicted place: ${place.name} at ${place.formatted_address}`
      }
    });

  };

  // Show the results of the query.
  service.getPlacePredictions(request, displaySuggestions);
}

检索自动补全预测结果(新)

借助新的 Place 类,您还可以以编程方式检索自动补全预测结果,从而比 PlaceAutocompleteElement 类更精细地控制用户界面。在以下示例中,系统针对“par”发出单个请求,其中 AutocompleteRequest 包含输入值和一组用于对预测进行偏置的界限。此示例返回一个 placePrediction 实例列表,并显示每个实例的说明。示例函数还会创建会话令牌并将其应用于请求。

async function init() {
  let sessionToken = new google.maps.places.AutocompleteSessionToken();

  // Define request options.
  let request = {
    input: "par",
    sessionToken: sessionToken,
    locationBias: {
      west: -122.44,
      north: 37.8,
      east: -122.39,
      south: 37.78,
    },
  };

  // Display the query string.
  const title = document.getElementById("title");
  title.appendChild(
    document.createTextNode('Place predictions for "' + request.input + '":'),
  );

  // Perform the query and display the results.
  const { suggestions } =
    await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

  const resultsElement = document.getElementById("results");

  for (let suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    const listItem = document.createElement("li");

    listItem.appendChild(
      document.createTextNode(placePrediction.text.text),
    );

    resultsElement.appendChild(listItem);
  }

  // Show the first predicted place.
  let place = suggestions[0].placePrediction.toPlace();

  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  const placeInfo = document.getElementById("prediction");

  placeInfo.textContent = `
    First predicted place: ${place.displayName} at ${place.formattedAddress}`
}

地点自动补全 widget

下表列出了 Places 服务(旧版)和 Place 类(新版)在自动补全 widget 使用方面的一些主要区别:

地点服务(旧版) 地点(新)
用于地点预测的 Autocomplete 类。 用于地点预测的 PlaceAutocompleteElement 类。
用于查询预测的 SearchBox
Autocomplete 类中没有查询预测。
只有默认的输入占位符文本会本地化。 文本输入占位符、预测列表徽标和地点预测均支持区域本地化。
widget 使用 setBounds()autocomplete.bindTo() 将搜索限制(偏向)到指定边界,并使用 strictBounds 将结果限制到指定边界。 微件使用 locationBias 属性将结果限定在指定边界内,并使用 locationRestriction 属性将搜索范围限定在指定边界内。
只能使用标准 HTML 输入元素来集成 widget。 可以使用标准 HTML 输入元素或 gmp-place-autocomplete 元素集成 widget。
使用该 widget 时,用户可能会请求无效的内容(例如“bisneyland”);必须明确处理这种情况。 该 widget 只会针对提供的建议返回结果,无法针对任意值发出请求;因此,无需处理可能无效的请求。
返回旧版 PlaceResult 实例。 返回 Place 实例。
地点数据字段设置为 Autocomplete 对象的选项。 当用户做出选择并调用 fetchFields() 时,系统会设置地点数据字段。
仅限于一组固定的地点类型地点数据字段 可访问更多地点类型地点数据字段

代码比较(微件)

本部分将比较自动补全的代码,以说明旧版地点自动补全微件与新版地点自动补全元素之间的区别。

地点自动补全 widget(旧版)

地点服务提供了两种自动补全 widget,您可以使用 AutocompleteSearchBox 类添加它们。每种 widget 都可以作为地图控件添加到地图中,也可以直接嵌入到网页中。以下代码示例展示了如何将 Autocomplete widget 嵌入为地图控件。

  • Autocomplete widget 构造函数有两个参数:
    • 一个是 text 类型的 HTML input 元素。自动补全服务将监控这个输入字段,并向该字段附加其搜索结果。
    • 一个可选的 AutocompleteOptions 实参,您可以在其中指定更多选项来限制查询。
  • 如需设置边界,可以通过调用 autocomplete.bindTo()Autocomplete 实例明确绑定到地图。
  • 在自动补全选项中指定地点数据字段。
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.749933, lng: -73.98633 },
    zoom: 13,
    mapTypeControl: false,
  });
  const card = document.getElementById("pac-card");
  const input = document.getElementById("pac-input");
  const options = {
    fields: ["formatted_address", "geometry", "name"],
    strictBounds: false,
  };

  map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);

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

  // Bind the map's bounds (viewport) property to the autocomplete object,
  // so that the autocomplete requests use the current map bounds for the
  // bounds option in the request.
  autocomplete.bindTo("bounds", map);

  const infowindow = new google.maps.InfoWindow();
  const infowindowContent = document.getElementById("infowindow-content");

  infowindow.setContent(infowindowContent);

  const marker = new google.maps.Marker({
    map,
    anchorPoint: new google.maps.Point(0, -29),
  });

  autocomplete.addListener("place_changed", () => {
    infowindow.close();
    marker.setVisible(false);

    const place = autocomplete.getPlace();

    if (!place.geometry || !place.geometry.location) {
      // User entered the name of a Place that was not suggested and
      // pressed the Enter key, or the Place Details request failed.
      window.alert("No details available for input: '" + place.name + "'");
      return;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17);
    }

    marker.setPosition(place.geometry.location);
    marker.setVisible(true);
    infowindowContent.children["place-name"].textContent = place.name;
    infowindowContent.children["place-address"].textContent =
      place.formatted_address;
    infowindow.open(map, marker);
  });
}

地点自动补全 widget(新)

Place 类提供 PlaceAutocompleteElementHTMLElement 子类),该类提供可作为地图控件添加到地图中或直接嵌入到网页中的界面组件。以下代码示例展示了如何将 PlaceAutocompleteElement widget 嵌入为地图控件。

地点自动补全 widget 在以下方面得到了改进:

  • Autocomplete widget 界面针对文本输入占位符、预测列表徽标和地点预测支持区域本地化(包括 RTL 语言)。
  • 增强了无障碍功能,包括对屏幕阅读器和键盘互动的支持。
  • Autocomplete widget 会返回新的 Place 类,以简化对返回对象的处理。
  • 为移动设备和小屏幕设备提供更好的支持。
  • 更出色的性能和改进的图形外观。

主要实现差异包括:

  • PlaceAutocompleteElement 提供自己的输入字段,并使用 HTML 或 JavaScript 直接插入到网页中(而不是提供现有的输入元素)。
  • Autocomplete 类中没有查询预测。
  • PlaceAutocompleteElement 是使用 PlaceAutocompleteElementOptions 构建的。
    • 地点数据字段是在选择时(调用 fetchFields() 时)指定的。
  • 使用 locationBoundslocationRestriction 选项设置边界。
let map;
let marker;
let infoWindow;

async function initMap() {
  // Request needed libraries.
  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,
  });

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

  placeAutocomplete.id = "place-autocomplete-input";
  const card = document.getElementById("place-autocomplete-card");

  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-select listener, and display the results on the map.
  placeAutocomplete.addEventListener("gmp-select", async ( place ) => {
    const place = event.placePrediction.toPlace();
    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,
  });
}