Google menyediakan akses yang mantap kepada API Petanya, yang boleh dimanfaatkan untuk pelbagai fungsi berasaskan lokasi dan tugas berkaitan peta. Dalam artikel ini, saya akan menerangkan cara kami menggunakan Google AutocompleteService API untuk membina medan Carian Alamat Pintar yang menggantikan borang alamat penuh.
Dengan menggunakan pendekatan ini, kami mengurangkan ralat input pengguna dan menambah baik pengalaman pengguna dengan memudahkan proses kemasukan alamat, menjadikannya lebih cepat dan tepat (1 input pintar lwn 3, huh).
Pertama sekali, untuk bekerja dengan API Peta, anda perlu mendayakannya dalam Platform Peta Google dan mendapatkan kunci API.
Dalam projek kami, kami menggunakan pakej @react-google-maps/api (npm i @react-google-maps/api).
Mari kita mulakan SDK dengan cangkuk useGoogleMapsApi tersuai, untuk menjadikannya boleh digunakan semula dalam aplikasi:
const useGoogleMapsApi = () => { const api = useJsApiLoader({ id: "app", googleMapsApiKey: "", // set your Public key }); return { ...api, }; };
Perkhidmatan Autolengkap Places menyediakan API untuk mencari dalam tempat. Ia menyediakan 2 kaedah:
Untuk melaksanakan carian kami, kami menggunakan kaedah getPlacePredictions(). Mari tambahkan kaedah ini pada kod kami dan kembalikannya dari cangkuk.
// Function to search for places using Google Autocomplete Service const searchPlaces = async ( query: string, options?: Omit<google.maps.places.AutocompletionRequest, "input"> ): Promise<Array<google.maps.places.AutocompletePrediction>> => { // Load AutocompleteService from Google Maps API const { AutocompleteService } = (await google.maps.importLibrary( "places" )) as google.maps.PlacesLibrary; const autocomplete = new AutocompleteService(); try { // Fetch place predictions based on user query const { predictions } = await autocomplete.getPlacePredictions({ ...options, // Optional additional parameters for more precise searches input: query, // User's search query (e.g., "Baker Street") }); // Return the list of predictions to display to the user return predictions; } catch { // If there's an error, return an empty array return []; } };
Antara muka AutocompletionRequest menggunakan medan input sebagai pertanyaan carian dan pilihan lain, yang membolehkan carian lebih tepat. Kami akan bercakap tentang mereka kemudian.
Kami akan menggunakan input mudah dan senarai keputusan untuk demo kami.
import useGoogleMapsApi from "./useGoogleMapsApi"; import { useEffect, useState } from "react"; export default function App() { const { searchPlaces } = useGoogleMapsApi(); // State to store input value from the user const [inputValue, setInputValue] = useState<string>(""); // State to store the list of place predictions from Google Autocomplete const [places, setPlaces] = useState< Array<google.maps.places.AutocompletePrediction> >([]); // Function to handle the search process when the user types a query const handleSearch = async (searchQuery: string) => { const result = await searchPlaces(searchQuery); setPlaces(result); }; // Trigger the search whenever the input value changes useEffect(() => { handleSearch(inputValue); }, [inputValue]); return ( <div style={{ maxWidth: "80%", width: "100%",fontFamily: "sans-serif",}}> <input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder="Find an address" /> {places.map((place) => ( <div style={{ marginBottom: "0.5rem",}}> <span style={{ color: "blue", cursor: "pointer",}}> {place.description} </span> <span style={{ color: "#333", fontSize: "0.75rem",}}>{`(${place.place_id})`}</span> <span> - {place.types.join(", ")}</span> </div> ))} </div> ); }
Dari ramalan, kami berminat dengan 3 bidang:
Antara muka AutocompleteService mempunyai banyak input, yang membolehkan carian dibuat dengan lebih tepat.
Sekatan komponen medan membolehkan kami mengecilkan hasil carian kepada satu negara tertentu. Ia menyokong sehingga 5 negara dan memerlukan kod negara berada dalam standard ISO 3166-1 Alpha-2. Di sini anda boleh menemui senarai kod negara.
const { predictions } = await autocomplete.getPlacePredictions({ ...options, input: query, componentRestrictions: { country: ["gb"], }, });
Untuk menjadikan medan kami tidak mengelirukan pengguna, kami perlu mengecualikan tempat seperti taman, lapangan terbang, dll daripada hasil carian. Perkhidmatan Autolengkap mempunyai jenis medan untuk menentukan jenis ramalan yang akan dikembalikan. Tetapi hanya satu jenis dibenarkan untuk AutocompleteService.
const { predictions } = await autocomplete.getPlacePredictions({ ...options, input: query, componentRestrictions: { country: ["gb"], }, types: ["geocode"], });
Tetapi ia juga termasuk entiti pentadbiran yang lebih besar seperti bandar atau jalanan. Kami memerlukan pengguna untuk memilih alamat yang tepat.
Gotcha! Itulah yang kita perlukan, bukan?... Pada asasnya, ya. Walau bagaimanapun, ia tidak membenarkan pengguna mencari melalui poskod, yang merupakan kes biasa bagi kami.
Jadi untuk mencapai hasil carian yang tepat mengikut kedua-dua nama jalan dan poskod, kami menulis penapis tersuai. Terima kasih kepada StackOverflow atas inspirasi.
export const filterPredictions = ( results: Array<google.maps.places.AutocompletePrediction> ): Array<google.maps.places.AutocompletePrediction> => results.filter(({ types }) => { // Keep predictions that are street addresses or postal codes if (types.includes("street_address") || types.includes("postal_code")) { return true; } // For geocode types, check for building numbers (premise/subpremise) if (types.includes("geocode")) { return types.some((type) => ["premise", "subpremise"].includes(type)); } return false; // Filter out irrelevant types });
Jika keputusan termasuk alamat_jalan atau pos_kod, kami menganggapnya sebagai hasil yang betul.
Jika ia mempunyai jenis geokod, kami menyemak premis atau subpremis (secara ringkasnya, nombor atau nama bangunan). Lagi tentang jenis yang anda boleh baca di sini.
Hasil yang kami capai:
AutocompleteService hanya mengembalikan ramalan carian, tetapi bukan butiran tempat yang kami perlukan. Walau bagaimanapun, dengan id tempat dan Geocoder kita boleh mendapatkan butiran seperti alamat tepat, negara, poskod dan koordinat.
Geocoder pada mulanya dicipta untuk membuat penukaran antara alamat dan koordinat, tetapi ia meliputi keperluan kami sepenuhnya.
Jika anda perlu mempunyai maklumat tambahan tentang tempat seperti ulasan dan ulasan, anda boleh menggunakan API Tempat.
Mari tambahkan kaedah baharu pada cangkuk kami:
// Function to get detailed information about a place using its place id const getPlaceById = async ( placeId: string // The place_id from the AutocompleteService ): Promise<google.maps.GeocoderResult | null> => { const geocoder = new google.maps.Geocoder(); // Create a new instance of Geocoder try { const { results } = await geocoder.geocode({ placeId }); // Return the first result return results[0]; } catch { // In case of error, return null return null; } };
Untuk menyatukan hasil antara daerah, di mana tahap pentadbiran dan entiti berbeza wujud, Google menggunakan struktur komponen alamat. Mari kita semak contoh:
To format the address, we need the Baker Street 221B, NW1 6XE, London (street_number route, postal_code, locality). But, in some cases, the keys structure might differ. To cover it we made an unified serializer:
// Helper function to extract a specific address component by its type (e.g., street_address, postal_code) export const pickAddressComponentByType = ( result: google.maps.GeocoderResult, type: Array<string> ): string => result.address_components.find((component) => component.types.some((componentType) => type.includes(componentType)) )?.long_name || ""; // Function to serialize the geocoded result into a structured format export const serializeGeocoderResult = ( result: google.maps.GeocoderResult ): TFormatedGeocoderResult => ({ formattedAddress: result.formatted_address, streetAddress: pickAddressComponentByType(result, [ "street_address", "premise", "route", ]), streetNumber: pickAddressComponentByType(result, ["street_number"]), city: pickAddressComponentByType(result, [ "locality", "postal_town", "administrative_area_level_2", ]), country: pickAddressComponentByType(result, ["country"]), state: pickAddressComponentByType(result, ["administrative_area_level_1"]), postalCode: pickAddressComponentByType(result, ["postal_code"]), latitude: result.geometry.location.lat(), longitude: result.geometry.location.lng(), });
Notice, that we verified it only for Great Britain. So maybe you might need to enhance it for your specific cases.
In this article, I have shown how we can use different Google Maps API's to build address fields, that can replace full address forms and drastically reduce the time users need to spend on it, reducing the number of mistakes on the users' side.
Check out the DEMO sandbox, but don’t forget to set your own GOOGLE_MAPS_API_KEY.
Feel free to send your questions and suggestions in comments. I'll be glad for any conversations??.
Atas ialah kandungan terperinci Mencipta Carian Alamat Pintar dengan API Peta Google dan React. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!