Yer Otomatik Tamamlama Verileri API'si, otomatik tamamlama widget'ı ile mümkün olandan daha hassas bir kontrol derecesiyle özelleştirilmiş otomatik tamamlama deneyimleri oluşturmak için yer tahminlerini programatik olarak almanıza olanak tanır. Bu kılavuzda, kullanıcı sorgularına dayalı otomatik tamamlama istekleri göndermek için Yer Adı Otomatik Tamamlama Verileri API'sini nasıl kullanacağınızı öğreneceksiniz.
Aşağıdaki örnekte basitleştirilmiş bir otomatik tamamlama entegrasyonu gösterilmektedir. Arama sorgunuzu (ör. "pizza" veya "poke") girin, ardından istediğiniz sonucu seçmek için tıklayın.
Otomatik tamamlama istekleri
Otomatik tamamlama isteği, sorgu giriş dizesini alır ve yer tahminlerinin listesini döndürür. Otomatik tamamlama isteğinde bulunmak için fetchAutocompleteSuggestions()
işlevini çağırın ve gerekli özelliklere sahip bir istek iletin. input
özelliği, aranacak dizeyi içerir. Normal bir uygulamada bu değer, kullanıcı sorgu yazarken güncellenir. İstek, faturalandırma amacıyla kullanılan bir sessionToken
içermelidir.
Aşağıdaki snippet'te, istek gövdesi oluşturma ve oturum jetonu ekleme, ardından fetchAutocompleteSuggestions()
çağrısı yaparak PlacePrediction
listesini alma işlemi gösterilmektedir.
// 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;
Otomatik tamamlama tahminlerini kısıtlama
Yer Otomatik Tamamlama, varsayılan olarak kullanıcının konumuna yakın tahminler için önyargılı bir şekilde tüm yer türlerini sunar ve kullanıcının seçtiği yer için mevcut tüm veri alanlarını getirir. Sonuçları kısıtlayarak veya yönlendirerek daha alakalı tahminler sunmak için Yer Otomatik Tamamlama seçeneklerini ayarlayın.
Sonuçların kısıtlanması, otomatik tamamlama widget'ının kısıtlama alanı dışında kalan sonuçları yoksaymasına neden olur. Sonuçları harita sınırlarıyla kısıtlamak yaygın bir uygulamadır. Sonuçları önyargılı hale getirmek, otomatik tamamlama widget'ının belirtilen alan içindeki sonuçları göstermesine neden olur ancak bazı eşleşmeler bu alanın dışında olabilir.
Hedefe olan jeodezik mesafenin hesaplanacağı başlangıç noktasını belirtmek için origin
özelliğini kullanın. Bu değer atlanırsa mesafe döndürülmez.
En fazla beş yer türü belirtmek için includedPrimaryTypes
özelliğini kullanın.
Tür belirtilmezse tüm türlerdeki yerler döndürülür.
Yer ayrıntılarını alma
Bir yer tahmini sonucundan Place
nesnesi döndürmek için önce toPlace()
işlevini, ardından da sonuçtaki Place
nesnesinde fetchFields()
işlevini çağırın (yer tahmininden gelen oturum kimliği otomatik olarak eklenir). Calling fetchFields()
, otomatik tamamlama oturumunu sonlandırır.
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;
Oturum jetonları
Oturum jetonları, kullanıcı otomatik tamamlama aramasının sorgu ve seçim aşamalarını faturalandırma amacıyla ayrı bir oturumda gruplandırır. Kullanıcı yazmaya başladığında oturum başlar. Kullanıcı bir yer seçtiğinde ve Yer Ayrıntıları'na çağrı yapıldığında oturum sona erer.
Yeni bir oturum jetonu oluşturup isteğe eklemek için AutocompleteSessionToken
örneği oluşturun,
ardından aşağıdaki snippet'te gösterildiği gibi jetonları kullanmak üzere isteğin sessionToken
özelliğini ayarlayın:
// Create a session token. const token = new AutocompleteSessionToken(); // Add the token to the request. // @ts-ignore request.sessionToken = token;
fetchFields()
çağrıldığında oturum sonlandırılır. Place
örneğini oluşturduktan sonra, oturum jetonunu fetchFields()
'ye iletmeniz gerekmez. Bu işlem otomatik olarak yapılır.
await place.fetchFields({ fields: ["displayName", "formattedAddress"], });
AutocompleteSessionToken
öğesinin yeni bir örneğini oluşturarak bir sonraki oturum için oturum jetonu oluşturun.
Oturum jetonu önerileri:
- Tüm Yer Otomatik Tamamlama çağrıları için oturum jetonlarını kullanın.
- Her oturum için yeni bir jeton oluşturun.
- Her yeni oturum için benzersiz bir oturum jetonu iletin. Aynı jetonun birden fazla oturumda kullanılması, her isteğin ayrı ayrı faturalandırılmasına neden olur.
İsteğe bağlı olarak, bir istekten otomatik tamamlama oturumu jetonunu çıkarabilirsiniz. Oturum jetonu atlanırsa her istek ayrı olarak faturalandırılır ve Otomatik Tamamlama - İstek Başına SKU'su tetiklenir. Oturum jetonunu yeniden kullanırsanız oturum geçersiz sayılır ve istekler, oturum jetonu sağlanmamış gibi ücretlendirilir.
Örnek
Kullanıcı sorgu yazarken birkaç tuş vuruşunda bir (karakter başına değil) otomatik tamamlama isteği çağrılır ve olası sonuçların listesi döndürülür. Kullanıcı sonuç listesinden seçim yaptığında bu seçim istek olarak kabul edilir ve arama sırasında yapılan tüm istekler paketlenip tek bir istek olarak sayılır. Kullanıcı bir yer seçerse arama sorgusu ücretsiz olarak kullanılabilir ve yalnızca yer verileri isteği için ödeme alınır. Kullanıcı, oturumun başlamasından sonraki birkaç dakika içinde seçim yapmazsa yalnızca arama sorgusu için ödeme alınır.
Bir uygulama açısından etkinlik akışı şu şekildedir:
- Bir kullanıcı, "Paris, Fransa"yı aramak için sorgu yazmaya başlıyor.
- Uygulama, kullanıcı girişini algıladığında yeni bir oturum jetonu ("Jeton A") oluşturur.
- Kullanıcı yazarken API, her birkaç karakterde bir otomatik tamamlama isteğinde bulunur ve her biri için olası sonuçların yeni bir listesini gösterir:
"P"
"Par"
"Paris,"
"Paris, Fr"
- Kullanıcı seçim yaptığında:
- Sorgudan kaynaklanan tüm istekler gruplandırılır ve "A Jetonu" ile temsil edilen oturuma tek bir istek olarak eklenir.
- Kullanıcının seçimi, Yer Ayrıntısı isteği olarak sayılır ve "A Jetonu" ile temsil edilen oturuma eklenir.
- Oturum sona erer ve uygulama "A Jetonu"nu siler.
Eksiksiz örnek kod
Bu bölümde, Yer Adı Otomatik Tamamlama Verileri API'sinin nasıl kullanılacağını gösteren eksiksiz örnekler yer almaktadır .Yer otomatik tamamlama tahminleri
Aşağıdaki örnekte, "Tadi" girişi için fetchAutocompleteSuggestions()
çağrısı yapılması, ardından ilk tahmin sonucu için toPlace()
çağrısı yapılması ve son olarak yer ayrıntılarını almak için fetchFields()
çağrısı yapılması gösterilmektedir.
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>
Örneği deneyin
Oturumlarla yer otomatik tamamlama yazarken bulma
Bu örnekte aşağıdaki kavramlar gösterilmektedir:
- Kullanıcı sorgularına göre
fetchAutocompleteSuggestions()
arama yapma ve yanıt olarak tahmin edilen yerlerin listesini gösterme - Kullanıcı sorgusunu son Yer Ayrıntıları isteğiyle gruplandırmak için oturum jetonlarını kullanma.
- Seçilen yerin ayrıntılarını alma ve bir işaretçi görüntüleme.
- Kullanıcı arayüzü öğelerini
gmp-map
öğesine yerleştirmek için kontrol yerleştirme özelliğini kullanma.
TypeScript
const mapElement = document.querySelector('gmp-map') as google.maps.MapElement; let innerMap: google.maps.Map; let marker: google.maps.marker.AdvancedMarkerElement; let titleElement = document.querySelector('.title') as HTMLElement; let resultsContainerElement = document.querySelector('.results') as HTMLElement; let inputElement = document.querySelector('input') as HTMLInputElement; let tokenStatusElement = document.querySelector('.token-status') as HTMLElement; let newestRequestId = 0; let tokenCount = 0; // Create an initial request body. const request: google.maps.places.AutocompleteRequest = { input: '', includedPrimaryTypes: [ 'restaurant', 'cafe', 'museum', 'park', 'botanical_garden', ], } async function init() { await google.maps.importLibrary('maps'); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, }); // Update request center and bounds when the map bounds change. google.maps.event.addListener(innerMap, 'bounds_changed', async () => { request.locationRestriction = innerMap.getBounds(); request.origin = innerMap.getCenter(); }); inputElement.addEventListener('input', makeAutocompleteRequest); } async function makeAutocompleteRequest(inputEvent) { // To avoid race conditions, store the request ID and compare after the request. const requestId = ++newestRequestId; const { AutocompleteSuggestion } = (await google.maps.importLibrary( 'places' )) as google.maps.PlacesLibrary; if (!inputEvent.target?.value) { titleElement.textContent = ''; resultsContainerElement.replaceChildren(); return; } // Add the latest char sequence to the request. request.input = (inputEvent.target as HTMLInputElement).value; // Fetch autocomplete suggestions and show them in a list. const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request); // If the request has been superseded by a newer request, do not render the output. if (requestId !== newestRequestId) return; titleElement.innerText = `Place predictions for "${request.input}"`; // Clear the list first. resultsContainerElement.replaceChildren(); for (const suggestion of suggestions) { const placePrediction = suggestion.placePrediction; if (!placePrediction) { continue; } // Create a link for the place, add an event handler to fetch the place. // We are using a button element to take advantage of its a11y capabilities. const placeButton = document.createElement('button'); placeButton.addEventListener('click', () => { onPlaceSelected(placePrediction.toPlace()); }); placeButton.textContent = placePrediction.text.toString(); placeButton.classList.add('place-button'); // Create a new list item element. const li = document.createElement('li'); li.appendChild(placeButton); resultsContainerElement.appendChild(li); } } // Event handler for clicking on a suggested place. async function onPlaceSelected(place: google.maps.places.Place) { const { AdvancedMarkerElement } = (await google.maps.importLibrary( 'marker' )) as google.maps.MarkerLibrary; await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'], }); resultsContainerElement.textContent = `${place.displayName}: ${place.formattedAddress}`; titleElement.textContent = 'Selected Place:'; inputElement.value = ''; await refreshToken(); // Remove the previous marker, if it exists. if (marker) { marker.remove(); } // Create a new marker. marker = new AdvancedMarkerElement({ map: innerMap, position: place.location, title: place.displayName, }) // Center the map on the selected place. if (place.location) { innerMap.setCenter(place.location); innerMap.setZoom(15); } } // Helper function to refresh the session token. async function refreshToken() { const { AutocompleteSessionToken } = (await google.maps.importLibrary( 'places' )) as google.maps.PlacesLibrary; // Increment the token counter. tokenCount++; // Create a new session token and add it to the request. request.sessionToken = new AutocompleteSessionToken(); tokenStatusElement.textContent = `Session token count: ${tokenCount}`; } init();
JavaScript
const mapElement = document.querySelector('gmp-map'); let innerMap; let marker; let titleElement = document.querySelector('.title'); let resultsContainerElement = document.querySelector('.results'); let inputElement = document.querySelector('input'); let tokenStatusElement = document.querySelector('.token-status'); let newestRequestId = 0; let tokenCount = 0; // Create an initial request body. const request = { input: '', includedPrimaryTypes: [ 'restaurant', 'cafe', 'museum', 'park', 'botanical_garden', ], }; async function init() { await google.maps.importLibrary('maps'); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, }); // Update request center and bounds when the map bounds change. google.maps.event.addListener(innerMap, 'bounds_changed', async () => { request.locationRestriction = innerMap.getBounds(); request.origin = innerMap.getCenter(); }); inputElement.addEventListener('input', makeAutocompleteRequest); } async function makeAutocompleteRequest(inputEvent) { // To avoid race conditions, store the request ID and compare after the request. const requestId = ++newestRequestId; const { AutocompleteSuggestion } = (await google.maps.importLibrary('places')); if (!inputEvent.target?.value) { titleElement.textContent = ''; resultsContainerElement.replaceChildren(); return; } // Add the latest char sequence to the request. request.input = inputEvent.target.value; // Fetch autocomplete suggestions and show them in a list. const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request); // If the request has been superseded by a newer request, do not render the output. if (requestId !== newestRequestId) return; titleElement.innerText = `Place predictions for "${request.input}"`; // Clear the list first. resultsContainerElement.replaceChildren(); for (const suggestion of suggestions) { const placePrediction = suggestion.placePrediction; if (!placePrediction) { continue; } // Create a link for the place, add an event handler to fetch the place. // We are using a button element to take advantage of its a11y capabilities. const placeButton = document.createElement('button'); placeButton.addEventListener('click', () => { onPlaceSelected(placePrediction.toPlace()); }); placeButton.textContent = placePrediction.text.toString(); placeButton.classList.add('place-button'); // Create a new list item element. const li = document.createElement('li'); li.appendChild(placeButton); resultsContainerElement.appendChild(li); } } // Event handler for clicking on a suggested place. async function onPlaceSelected(place) { const { AdvancedMarkerElement } = (await google.maps.importLibrary('marker')); await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'], }); resultsContainerElement.textContent = `${place.displayName}: ${place.formattedAddress}`; titleElement.textContent = 'Selected Place:'; inputElement.value = ''; await refreshToken(); // Remove the previous marker, if it exists. if (marker) { marker.remove(); } // Create a new marker. marker = new AdvancedMarkerElement({ map: innerMap, position: place.location, title: place.displayName, }); // Center the map on the selected place. if (place.location) { innerMap.setCenter(place.location); innerMap.setZoom(15); } } // Helper function to refresh the session token. async function refreshToken() { const { AutocompleteSessionToken } = (await google.maps.importLibrary('places')); // Increment the token counter. tokenCount++; // Create a new session token and add it to the request. request.sessionToken = new AutocompleteSessionToken(); tokenStatusElement.textContent = `Session token count: ${tokenCount}`; } 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; } .place-button { height: 3rem; width: 100%; background-color: transparent; text-align: left; border: none; cursor: pointer; } .place-button:focus-visible { outline: 2px solid #0056b3; border-radius: 2px; } .input { width: 300px; font-size: small; margin-bottom: 1rem; } /* Styles for the floating panel */ .controls { background-color: #fff; border-radius: 8px; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); font-family: sans-serif; font-size: small; margin: 12px; padding: 1rem; } .title { font-weight: bold; margin-top: 1rem; margin-bottom: 0.5rem; } .results { list-style-type: none; margin: 0; padding: 0; } .results li:not(:last-child) { border-bottom: 1px solid #ddd; } .results li:hover { background-color: #eee; }
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> <!-- 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> </head> <body> <gmp-map center="37.7893, -122.4039" zoom="12" map-id="DEMO_MAP_ID"> <div class="controls" slot="control-inline-start-block-start" > <input type="text" class="input" placeholder="Search for a place..." autocomplete="off" /><!-- Turn off the input's own autocomplete (not supported by all browsers).--> <div class="token-status"></div> <div class="title"></div> <ol class="results"></ol> </div> </gmp-map> </body> </html>