Interfejs Place Autocomplete Data API

Deweloperzy z Europejskiego Obszaru Gospodarczego (EOG)

Interfejs Place Autocomplete Data API umożliwia programowe pobieranie prognozowanych lokalizacji, aby tworzyć dostosowane funkcje autouzupełniania z większą kontrolą niż w przypadku widżetu autouzupełniania. Z tego przewodnika dowiesz się, jak korzystać z interfejsu Place Autocomplete Data API do wysyłania żądań autouzupełniania na podstawie zapytań użytkowników.

Poniższy przykład przedstawia uproszczoną integrację funkcji wpisywania z wyprzedzeniem. Wpisz zapytanie, np. „pizza” lub „poke”, a potem kliknij, aby wybrać odpowiedni wynik.

Żądania autouzupełniania

Żądanie autouzupełniania przyjmuje ciąg wejściowy zapytania i zwraca listę prognoz miejsc. Aby wysłać żądanie autouzupełniania, wywołaj funkcję fetchAutocompleteSuggestions() i przekaż żądanie z wymaganymi właściwościami. Właściwość input zawiera ciąg znaków do wyszukania. W typowym zastosowaniu ta wartość jest aktualizowana w miarę wpisywania zapytania przez użytkownika. Żądanie powinno zawierać sessionToken, który jest używany do celów rozliczeniowych.

Poniższy fragment kodu pokazuje tworzenie treści żądania i dodawanie tokena sesji, a następnie wywoływanie funkcji fetchAutocompleteSuggestions() w celu uzyskania listy PlacePrediction.

// Add an initial request body.
let request = {
  input: "Tadi",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};
// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

Ograniczanie podpowiedzi autouzupełniania

Domyślnie autouzupełnianie miejsc wyświetla wszystkie typy miejsc, z większym prawdopodobieństwem prognozowania w pobliżu lokalizacji użytkownika, i pobiera wszystkie dostępne pola danych dla wybranego przez użytkownika miejsca. Ustaw opcje autouzupełniania miejsca, aby wyświetlać bardziej trafne prognozy, ograniczając lub modyfikując wyniki.

Ograniczenie wyników powoduje, że widżet autouzupełniania ignoruje wszystkie wyniki, które znajdują się poza obszarem ograniczenia. Często stosowaną praktyką jest ograniczanie wyników do granic mapy. W przypadku wyników z odchyleniem widżet autouzupełniania wyświetla wyniki w określonym obszarze, ale niektóre dopasowania mogą znajdować się poza tym obszarem.

Użyj właściwości origin, aby określić punkt początkowy, od którego ma być obliczana odległość geodezyjna do miejsca docelowego. Jeśli ta wartość zostanie pominięta, odległość nie zostanie zwrócona.

Użyj właściwości includedPrimaryTypes, aby określić maksymalnie 5 typów miejsc. Jeśli nie określisz żadnych typów, zwracane będą miejsca wszystkich typów.

Zobacz dokumentację API

Pobieranie szczegółów miejsca

Aby zwrócić obiekt Place z wyniku prognozy miejsca, najpierw wywołaj toPlace(), a potem wywołaj fetchFields() na wynikowym obiekcie Place (identyfikator sesji z prognozy miejsca jest uwzględniany automatycznie). Wywołanie fetchFields() kończy sesję autouzupełniania.

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

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

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

placeInfo.textContent =
  "First predicted place: " +
  place.displayName +
  ": " +
  place.formattedAddress;

Tokeny sesji

Tokeny sesji grupują fazy zapytania i wyboru autouzupełniania wyszukiwania użytkownika w osobną sesję na potrzeby rozliczeń. Sesja rozpoczyna się, gdy użytkownik zaczyna pisać. Sesja kończy się, gdy użytkownik wybierze miejsce i wywoła wywołanie szczegółów miejsca.

Aby utworzyć nowy token sesji i dodać go do żądania, utwórz instancję AutocompleteSessionToken, a potem ustaw właściwość sessionToken żądania, aby używać tokenów, jak pokazano w tym fragmencie kodu:

// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

Sesja kończy się po wywołaniu funkcji fetchFields(). Po utworzeniu instancji Place nie musisz przekazywać tokena sesji do fetchFields(), ponieważ jest to obsługiwane automatycznie.

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

Utwórz token sesji na potrzeby następnej sesji, tworząc nową instancję AutocompleteSessionToken.

Rekomendacje dotyczące tokena sesji:

  • Używaj tokenów sesji we wszystkich wywołaniach funkcji Autouzupełnianie miejsc.
  • Generuj nowy token dla każdej sesji.
  • W przypadku każdej nowej sesji przekaż unikalny token sesji. Użycie tego samego tokena w więcej niż 1 sesji spowoduje naliczenie opłaty za każde żądanie osobno.

Opcjonalnie możesz pominąć w żądaniu token sesji autouzupełniania. Jeśli token sesji zostanie pominięty, każde żądanie będzie rozliczane osobno, co spowoduje użycie kodu SKU Autocomplete – za żądanie. Jeśli ponownie użyjesz tokena sesji, sesja zostanie uznana za nieprawidłową, a żądania zostaną obciążone opłatą tak, jakby token sesji nie został podany.

Przykład

Gdy użytkownik wpisuje zapytanie, co kilka naciśnięć klawiszy (nie po każdym znaku) wysyłane jest żądanie autouzupełniania i zwracana jest lista możliwych wyników. Gdy użytkownik wybierze element z listy wyników, wybór ten jest traktowany jako żądanie. Wszystkie żądania wysłane podczas wyszukiwania są łączone i traktowane jako jedno żądanie. Jeśli użytkownik wybierze miejsce, zapytanie jest dostępne bezpłatnie, a opłata jest naliczana tylko za żądanie danych o miejscu. Jeśli użytkownik nie dokona wyboru w ciągu kilku minut od rozpoczęcia sesji, zostanie naliczona opłata tylko za zapytanie.

Z perspektywy aplikacji przepływ zdarzeń wygląda tak:

  1. Użytkownik zaczyna wpisywać zapytanie, aby wyszukać „Paryż, Francja”.
  2. Po wykryciu danych wejściowych użytkownika aplikacja tworzy nowy token sesji „Token A”.
  3. Gdy użytkownik wpisuje tekst, interfejs API wysyła co kilka znaków żądanie autouzupełniania i wyświetla nową listę potencjalnych wyników:
    „P”
    „Par”
    „Paryż”
    „Paryż, Fr”
  4. Gdy użytkownik dokona wyboru:
    • Wszystkie żądania wynikające z zapytania są grupowane i dodawane do sesji reprezentowanej przez „Token A” jako jedno żądanie.
    • Wybór użytkownika jest liczony jako żądanie szczegółów miejsca i dodawany do sesji reprezentowanej przez „Token A”.
  5. Sesja zostaje zakończona, a aplikacja odrzuca „Token A”.
Więcej informacji o płatnościach za sesje

Pełny przykładowy kod

Ta sekcja zawiera kompletne przykłady pokazujące, jak korzystać z interfejsu Place Autocomplete Data API .

Podpowiedzi autouzupełniania miejsc

W tym przykładzie pokazujemy wywołanie funkcji fetchAutocompleteSuggestions() dla danych wejściowych „Tadi”, a następnie wywołanie funkcji toPlace() na pierwszym wyniku prognozy i wywołanie funkcji fetchFields() w celu uzyskania szczegółów miejsca.

TypeScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
    // @ts-ignore
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary;

    // Add an initial request body.
    let request = {
        input: "Tadi",
        locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ["restaurant"],
        language: "en-US",
        region: "us",
    };

    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    const title = document.getElementById('title') as HTMLElement;
    title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":'));

    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a new list element.
        const listItem = document.createElement('li');
        const resultsElement = document.getElementById("results") as HTMLElement;
        listItem.appendChild(document.createTextNode(placePrediction.text.toString()));
        resultsElement.appendChild(listItem);
    }

    let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });

    const placeInfo = document.getElementById("prediction") as HTMLElement;
    placeInfo.textContent = 'First predicted place: ' + place.displayName + ': ' + place.formattedAddress;

}

init();

JavaScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
  // @ts-ignore
  const { Place, AutocompleteSessionToken, AutocompleteSuggestion } =
    await google.maps.importLibrary("places");
  // Add an initial request body.
  let request = {
    input: "Tadi",
    locationRestriction: {
      west: -122.44,
      north: 37.8,
      east: -122.39,
      south: 37.78,
    },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
  };
  // Create a session token.
  const token = new AutocompleteSessionToken();

  // Add the token to the request.
  // @ts-ignore
  request.sessionToken = token;

  // Fetch autocomplete suggestions.
  const { suggestions } =
    await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
  const title = document.getElementById("title");

  title.appendChild(
    document.createTextNode('Query predictions for "' + request.input + '":'),
  );

  for (let suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a new list element.
    const listItem = document.createElement("li");
    const resultsElement = document.getElementById("results");

    listItem.appendChild(
      document.createTextNode(placePrediction.text.toString()),
    );
    resultsElement.appendChild(listItem);
  }

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

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

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

  placeInfo.textContent =
    "First predicted place: " +
    place.displayName +
    ": " +
    place.formattedAddress;
}

init();

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

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Predictions</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="title"></div>
    <ul id="results"></ul>
    <p><span id="prediction"></span></p>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- 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: "weekly"});</script>
  </body>
</html>

Wypróbuj przykład

Autouzupełnianie miejsc z sesjami

W tym przykładzie pokazujemy, jak wywołać funkcję fetchAutocompleteSuggestions() na podstawie zapytań użytkownika, wyświetlić listę przewidywanych miejsc w odpowiedzi na zapytanie i pobrać szczegóły wybranego miejsca. Przykład pokazuje też użycie tokenów sesji do grupowania zapytania użytkownika z końcowym żądaniem szczegółów miejsca.

TypeScript

let titleElement;
let resultsContainerElement;
let inputElement;

let newestRequestId = 0;

// Add an initial request body.
const request = {
    input: '',
    locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ['restaurant'],
    language: 'en-US',
    region: 'us',
};

function init() {
    titleElement = document.getElementById('title');
    resultsContainerElement = document.getElementById('results');
    inputElement = document.querySelector('input');
    inputElement.addEventListener('input', makeAutocompleteRequest);
    refreshToken(request);
}

async function makeAutocompleteRequest(inputEvent) {
    // Reset elements and exit if an empty string is received.
    if (inputEvent.target.value == '') {
        titleElement.innerText = '';
        resultsContainerElement.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = inputEvent.target.value;

    // To avoid race conditions, store the request ID and compare after the request.
    const requestId = ++newestRequestId;

    // Fetch autocomplete suggestions and show them in a list.
    // @ts-ignore
    const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    // If the request has been superseded by a newer request, do not render the output.
    if (requestId !== newestRequestId) return;

    titleElement.innerText = `Query predictions for "${request.input}"`;

    // Clear the list first.
    resultsContainerElement.replaceChildren();

    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a link for the place, add an event handler to fetch the place.
        const a = document.createElement('a');
        a.addEventListener('click', () => {
            onPlaceSelected(placePrediction!.toPlace());
        });
        a.innerText = placePrediction!.text.toString();

        // Create a new list item element.
        const li = document.createElement('li');
        li.appendChild(a);
        resultsContainerElement.appendChild(li);
    }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    const placeText = document.createTextNode(`${place.displayName}: ${place.formattedAddress}`);
    resultsContainerElement.replaceChildren(placeText);
    titleElement.innerText = 'Selected Place:';
    inputElement.value = '';
    refreshToken(request);
}

// Helper function to refresh the session token.
function refreshToken(request) {
    // Create a new session token and add it to the request.
    request.sessionToken = new google.maps.places.AutocompleteSessionToken();
}

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

JavaScript

let titleElement;
let resultsContainerElement;
let inputElement;
let newestRequestId = 0;
// Add an initial request body.
const request = {
    input: '',
    locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ['restaurant'],
    language: 'en-US',
    region: 'us',
};
function init() {
    titleElement = document.getElementById('title');
    resultsContainerElement = document.getElementById('results');
    inputElement = document.querySelector('input');
    inputElement.addEventListener('input', makeAutocompleteRequest);
    refreshToken(request);
}
async function makeAutocompleteRequest(inputEvent) {
    // Reset elements and exit if an empty string is received.
    if (inputEvent.target.value == '') {
        titleElement.innerText = '';
        resultsContainerElement.replaceChildren();
        return;
    }
    // Add the latest char sequence to the request.
    request.input = inputEvent.target.value;
    // To avoid race conditions, store the request ID and compare after the request.
    const requestId = ++newestRequestId;
    // Fetch autocomplete suggestions and show them in a list.
    // @ts-ignore
    const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
    // If the request has been superseded by a newer request, do not render the output.
    if (requestId !== newestRequestId)
        return;
    titleElement.innerText = `Query predictions for "${request.input}"`;
    // Clear the list first.
    resultsContainerElement.replaceChildren();
    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;
        // Create a link for the place, add an event handler to fetch the place.
        const a = document.createElement('a');
        a.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        a.innerText = placePrediction.text.toString();
        // Create a new list item element.
        const li = document.createElement('li');
        li.appendChild(a);
        resultsContainerElement.appendChild(li);
    }
}
// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    const placeText = document.createTextNode(`${place.displayName}: ${place.formattedAddress}`);
    resultsContainerElement.replaceChildren(placeText);
    titleElement.innerText = 'Selected Place:';
    inputElement.value = '';
    refreshToken(request);
}
// Helper function to refresh the session token.
function refreshToken(request) {
    // Create a new session token and add it to the request.
    request.sessionToken = new google.maps.places.AutocompleteSessionToken();
}
window.init = init;

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

a {
  cursor: pointer;
  text-decoration: underline;
  color: blue;
}

input {
  width: 300px;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Session</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <input id="input" type="text" placeholder="Search for a place..." />
    <div id="title"></div>
    <ul id="results"></ul>
    <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 script 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=AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8&callback=init&libraries=places&v=weekly"
      defer
    ></script>
  </body>
</html>

Wypróbuj przykład