如何在Google Maps API拖拽标记时获取自动补全地址组件
Hey there, I see the issue you're facing. The autocomplete works great when searching, but when you drag the marker or click the map, the address fields don't update because there's no code handling those events to fetch the new address components. Let's fix that!
Here's what we need to do:
- Make the marker draggable so users can move it around
- Add event listeners for when the marker stops dragging and when the map is clicked
- Use the geocoder to reverse-lookup the address from the new coordinates, then update all the address fields just like the autocomplete does
Here's your modified code with these changes:
<head> <title>Place Autocomplete Address Form</title> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500"> <style> /* 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; } #locationField, #controls { position: relative; width: 480px; } #autocomplete { position: absolute; top: 0px; left: 0px; width: 99%; } .label { text-align: right; font-weight: bold; width: 100px; color: #303030; } #address { border: 1px solid #000090; background-color: #f0f0ff; width: 480px; padding-right: 2px; } #address td { font-size: 10pt; } .field { width: 99%; } .slimField { width: 80px; } .wideField { width: 200px; } #locationField { height: 20px; margin-bottom: 2px; } </style> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyA1BvEkX8v91LRu43HQe0-GNaHTVnoTSQs&libraries=places&callback=initMap" async defer></script> </head> <body> <br><br> <div id="locationField"> <input id="autocomplete" placeholder="Enter your address" type="text"></input> </div> <table id="address"> <tr> <td class="label">Street address</td> <td class="slimField"><input class="field" id="street_number" disabled="true" name="streetnumber"></input></td> <td class="wideField" colspan="2"><input class="field" id="route" disabled="true" name="route"></input></td> </tr> <tr> <td class="label">City</td> <td class="wideField" colspan="3"><input class="field" id="locality" disabled="true" name="locality"></input></td> </tr> <tr> <td class="label">State</td> <td class="slimField"><input class="field" id="administrative_area_level_1" disabled="true" name="state" ></input></td> <td class="label">Zip code</td> <td class="wideField"><input class="field" id="postal_code" disabled="true" name="postal_code"></input></td> </tr> <tr> <td class="label">Country</td> <td class="wideField" colspan="3"><input class="field" id="country" disabled="true" name="country"></input></td> </tr> </table> <div id="map" style="width: 50%; height: 250px;"></div> <div id="infowindow-content"> <img src="" width="16" height="16" id="place-icon"> <span id="place-name" class="title"></span><br> <span id="place-address"></span> </div> <script> var componentForm = { street_number: 'short_name', route: 'long_name', locality: 'long_name', administrative_area_level_1: 'short_name', country: 'long_name', postal_code: 'short_name' }; var input = document.getElementById('autocomplete'); function initMap() { var geocoder; var autocomplete; geocoder = new google.maps.Geocoder(); var map = new google.maps.Map(document.getElementById('map'), { center: {lat: -33.8688, lng: 151.2195}, zoom: 13 }); var card = document.getElementById('locationField'); autocomplete = new google.maps.places.Autocomplete(input); // Bind the map's bounds to the autocomplete object autocomplete.bindTo('bounds', map); var infowindow = new google.maps.InfoWindow(); var infowindowContent = document.getElementById('infowindow-content'); infowindow.setContent(infowindowContent); // Create draggable marker var marker = new google.maps.Marker({ map: map, anchorPoint: new google.maps.Point(0, -29), draggable: true // Make marker draggable }); // Handle autocomplete place selection autocomplete.addListener('place_changed', function() { infowindow.close(); var place = autocomplete.getPlace(); if (!place.geometry) { 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); // Fill in address fields from autocomplete place fillInAddress(place); }); // Update address when marker is dragged marker.addListener('dragend', function() { updateAddressFromLatLng(this.getPosition()); }); // Update address when map is clicked map.addListener('click', function(e) { marker.setPosition(e.latLng); updateAddressFromLatLng(e.latLng); }); // Function to fill address fields from place object function fillInAddress(place) { for (var component in componentForm) { document.getElementById(component).value = ''; document.getElementById(component).disabled = false; } // Get each component of the address from the place details, // and fill the corresponding field on the form. for (var i = 0; i < place.address_components.length; i++) { var addressType = place.address_components[i].types[0]; if (componentForm[addressType]) { var val = place.address_components[i][componentForm[addressType]]; document.getElementById(addressType).value = val; } } // Update infowindow infowindowContent.getElementById('place-name').textContent = place.name; infowindowContent.getElementById('place-address').textContent = place.formatted_address; infowindow.open(map, marker); } // Function to update address from LatLng using reverse geocoding function updateAddressFromLatLng(latLng) { geocoder.geocode({ 'location': latLng }, function(results, status) { if (status === 'OK' && results[0]) { // Update autocomplete input with full address input.value = results[0].formatted_address; // Clear existing fields for (var component in componentForm) { document.getElementById(component).value = ''; } // Fill address fields from geocode results results[0].address_components.forEach(function(component) { var componentType = component.types[0]; if (componentForm[componentType]) { var val = component[componentForm[componentType]]; document.getElementById(componentType).value = val; } }); // Update infowindow infowindowContent.getElementById('place-name').textContent = results[0].name || results[0].formatted_address; infowindowContent.getElementById('place-address').textContent = results[0].formatted_address; infowindow.open(map, marker); } else { console.error('Geocode failed: ' + status); window.alert('Could not retrieve address for this location.'); } }); } } </script> </body>
Key Changes Explained:
- Draggable Marker: Added
draggable: trueto the marker initialization so users can move it. - Event Listeners: Added listeners for
dragend(when marker stops moving) and mapclick(to place marker at clicked location). - Reverse Geocoding: The
updateAddressFromLatLngfunction takes coordinates, uses the geocoder to get address components, and updates all form fields just like the autocomplete does. - Consistent Updates: Ensures the autocomplete input field and infowindow also get updated when the marker is moved.
Now when you drag the marker or click anywhere on the map, all the address fields (street number, city, state, etc.) will automatically update to match the new location.
内容的提问来源于stack exchange,提问作者somesh
相关产品推荐
相关产品推荐

