Ich liebe es, online einzukaufen. Ich kann finden, was ich brauche, und die meisten Dinge zu einem ordentlichen Preis bekommen. Ich bin Nigerianer, arbeite und studiere derzeit in Indien, und zwei Dinge, die ich beim Online-Shopping fürchte, sind
- Ausfüllen eines Kreditkartenformulars
- Ausfüllen von Versand- und Rechnungsadressformularen
Vielleicht bin ich einfach nur faul, aber diese Dinge sind nicht ohne Herausforderungen! Für erstere, dank Zahlungsabwicklungsdiensten wie PayPal und E-Wallets, muss ich weder meine 12-stellige Kreditkartennummer für jede neue E-Commerce-Seite, die ich besuche, eingeben, noch meine Kreditkartendaten dort speichern.
Für letztere ist die einzige zeitsparende Option, die die meisten Shopping-Websites anbieten, die Speicherung Ihrer Versandadresse. Sie müssen das Formular aber immer noch ausfüllen (arrrghh!). Hier liegt die Herausforderung. Die meisten meiner Bestellungen wurden zurückgeschickt, weil meine Adresse (von der ich *dachte*, sie sei die richtige) aus dem einen oder anderen Grund von der App nicht gefunden oder bestätigt werden konnte.
Adresseneingaben sind herausfordernd
Die Erfassung der Adresse eines Benutzers über ein Eingabeformular ist eine saubere Lösung, kann aber auch für den Benutzer eine Herkulesaufgabe sein. Hier ist, warum:
- Wenn der Benutzer in einer bestimmten Stadt neu ist, kennt er möglicherweise seine vollständige Adresse nicht.
- Wenn der Benutzer an eine neue Adresse versenden möchte, die nicht gespeichert ist (z. B. Versand an einen Arbeitsplatz oder die Adresse eines Freundes anstelle der gespeicherten Heimatadresse).
- Wenn der Benutzer in einer Stadt mit sehr schwierigen Adresssystemen lebt.
- Wenn der Benutzer einfach nur faul ist wie ich.
Eine mögliche Lösung: Adresse automatisch abrufen
Die Adresse des Benutzers per Tippen/Klick auf einen Button zu erhalten. Ja, das ist einfach! Die Benutzererfahrung ist großartig, da sie dem Benutzer sowohl Zeit als auch Mühe beim Ausfüllen eines Formulars erspart. Sie wird auch dem Ladenbesitzer Zeit, Mühe und in einigen Fällen sogar Geld sparen, da die Anzahl falsch platzierter Bestellungen oder Sendungen wahrscheinlich reduziert wird.
Lassen Sie uns eine Mini-App erstellen, die die Adresse eines Benutzers abruft und sie auf einer Google Maps-Oberfläche mit Vanilla JavaScript anzeigt. Das Konzept ist wie folgt:
- HTML-Button abrufen und auf ein Klickereignis hören.
- Benutzerstandort (Breiten- und Längengrad) bei Button-Klick abrufen.
- Benutzerstandort auf einer Google Map anzeigen.
- Breiten- und Längengrad an die Google Maps Geocoding API URL übergeben.
- Die zurückgegebene Adresse (oder Liste von Adressen) auf der Benutzeroberfläche anzeigen, damit der Benutzer eine auswählen kann.
- Auf Kartenereignisse hören und Schritte 4 und 5 wiederholen.
- Das Formular mit den vom Benutzer ausgewählten Adressdaten vorausfüllen.
Erste Schritte und Einrichtung
Um diese App zu erstellen, verwenden wir das Materialize CSS-Framework, um uns Zeit beim Styling zu sparen. Materialize ist ein modernes, responsives Front-End-Framework, das auf dem Material Design-System von Google basiert. Die Beta-Version funktioniert mit Vanilla JavaScript.
Ein grundlegendes Setup mit den CSS- und JavaScript-Dateien von Materialize in einem Dokument sieht so aus:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Address Locator</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
Wir werden auch die Google Maps API verwenden, um die Karte anzuzeigen und die menschenlesbare Adresse des Benutzers zu erhalten. Dazu benötigen wir einen API-Schlüssel. Hier erfahren Sie, wie Sie einen erhalten:
- Melden Sie sich bei Ihrem Google Developer Console-Konto an.
- Erstellen Sie ein neues Projekt oder wählen Sie ein bestehendes aus.
- Klicken Sie auf „APIs und Dienste aktivieren“.
- Wählen Sie die Option „Maps Javascript API“ aus.
- Klicken Sie auf der neuen Seite, die sich öffnet, auf „Aktivieren“. Gehen Sie zur vorherigen Seite zurück und suchen Sie nach „Geocoding API“, klicken Sie darauf und aktivieren Sie sie ebenfalls.
- Klicken Sie dann in der rechten Navigationsleiste der Seite auf „Credentials“, kopieren Sie den API-Schlüssel auf der Seite und speichern Sie ihn in einer Datei.
Aktualisieren wir nun unser Dokument, um die Karte anzuzeigen und den Benutzer darüber zu informieren, dass sie zur Ermittlung seiner aktuellen Adresse verwendet werden kann. Außerdem fügen wir ein Formular hinzu, das mit der vom Benutzer ausgewählten Adresse vorausgefüllt wird.
...
<body>
<div class="container">
<h3>Shipping Address</h3>
<p>You can click the button below to use your current location as your shipping address</p>
<div id="map">
</div>
<button id="showMe" class="btn">Use My Location</button>
<form id="shippingAddress">
<div id="locationList"></div>
<br>
<div class="input-field">
<textarea class="input_fields materialize-textarea" id="address" type="text"></textarea>
<label class="active" for="address">Address (Area and Street)</label>
</div>
<div class="input-field">
<input class="input_fields" id="locality" type="text">
<label class="active" for="locality">Locality</label>
</div>
<div class="input-field">
<input class="input_fields" id="city" type="text">
<label class="active" for="city">City/District/Town</label>
</div>
<div class="input-field">
<input class="input_fields" id="postal_code" type="text">
<label class="active" for="pin_code">Pin Code</label>
</div>
<div class="input-field">
<input class="input_fields" id="landmark" type="text">
<label class="active" for="landmark">Landmark</label>
</div>
<div class="input-field">
<input class="input_fields" id="state" type="text">
<label class="active" for="State">State</label>
</div>
</form>
<!-- You could add a fallback address gathering form here -->
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
<script src="js/main.js"></script>
</body>
</html>
Während wir dabei sind, stylen wir die Dinge ein wenig, um dies etwas besser aussehen zu lassen.
.container {
width: 50%;
max-width: 800px;
}
#map {
height: 50vh;
margin-bottom: 10px;
display: none;
}
#locationList .card {
padding: 10px;
}
#toast-container {
top: 50%;
bottom: unset;
}
.toast {
background-color: rgba(0, 0, 0, 0.8);
}
@media only screen and (max-width: 768px) {
.container {
width: 80%;
}
}
Dieses CSS verbirgt die Karte, bis wir bereit sind, sie anzuzeigen. Unsere App sollte dann so aussehen:

Lasst uns das planen
Unsere App nutzt die HTML5 Geolocation API, um den aktuellen Standort unseres Benutzers zu ermitteln, sowie die Geocoding API von Google mit einer Technik namens Reverse Geocoding. Die Geocoding API nimmt eine menschenlesbare Adresse entgegen und wandelt sie in geografische Koordinaten (Breiten- und Längengrad) um und markiert den Punkt auf der Karte.
Reverse Geocoding macht das Gegenteil. Es nimmt den Breiten- und Längengrad und wandelt sie in menschenlesbare Adressen um. Geocoding und Reverse Geocoding sind gut dokumentiert.
So wird unsere App funktionieren:
- Der Benutzer klickt auf die Schaltfläche „Meinen Standort verwenden“.
- Der Benutzer wird mit der HTML5 Geolocation API (
navigator.geolocation) lokalisiert. - Wir erhalten die geografischen Koordinaten des Benutzers.
- Wir übergeben die Koordinaten an die Geocoding-Anfrage-API.
- Wir zeigen die resultierenden Adressen dem Benutzer an.
Meistens gibt die Geokodierung *mehrere Adressen* zurück, sodass wir dem Benutzer alle zurückgegebenen Adressen anzeigen und ihn die genaueste auswählen lassen müssen.
Puh! Endlich können wir zum unterhaltsamen Teil des Schreibens des JavaScripts übergehen. Lassen Sie uns die einzelnen Schritte durchgehen, die wir skizziert haben.
Schritt 1: Button klicken
In unserer Datei main.js holen wir uns eine Referenz auf den HTML-Button. Während wir dabei sind, richten wir einige andere Variablen ein, die wir benötigen werden, wie unseren API-Schlüssel.
//This div will display Google map
const mapArea = document.getElementById('map');
//This button will set everything into motion when clicked
const actionBtn = document.getElementById('showMe');
//This will display all the available addresses returned by Google's Geocode Api
const locationsAvailable = document.getElementById('locationList');
//Let's bring in our API_KEY
const __KEY = 'YOUR_API_KEY';
//Let's declare our Gmap and Gmarker variables that will hold the Map and Marker Objects later on
let Gmap;
let Gmarker;
//Now we listen for a click event on our button
actionBtn.addEventListener('click', e => {
// hide the button
actionBtn.style.display = "none";
// call Materialize toast to update user
M.toast({ html: 'fetching your current location', classes: 'rounded' });
// get the user's position
getLocation();
});
Wenn der Klick-Handler für unseren Button ausgeführt wird, dann:
- Verbirgt sich der Button.
- Benachrichtigt den Benutzer, dass wir seinen aktuellen Standort abrufen (ein „Toast“ in Materialize ist wie eine Pop-up-Benachrichtigung).
- Ruft die Funktion
getLocationauf.
Schritt 2: Benutzerstandort (Breiten- und Längengrad) abrufen
Wenn unsere Funktion getLocation aufgerufen wird, müssen wir weitere Arbeiten durchführen. Zuerst prüfen wir, ob wir die Geolocation API überhaupt nutzen können.
getLocation = () => {
// check if user's browser supports Navigator.geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayLocation, showError, options);
} else {
M.toast({ html: "Sorry, your browser does not support this feature... Please Update your Browser to enjoy it", classes: "rounded" });
}
}
Wenn Unterstützung vorhanden ist, wird die Methode getCurrentPosition von Geolocation aufgerufen. Wenn keine Unterstützung vorhanden ist, wird der Benutzer benachrichtigt, dass es keine Browserunterstützung gibt.
Wenn Unterstützung vorhanden ist, wird die Methode getCurrentLocation verwendet, um den aktuellen Standort des Geräts abzurufen. Die Syntax lautet wie folgt:
navigator.geolocation.getCurrentPosition(*success, error, [options]*)
success: Dies ist eine Callback-Funktion, die eine Position als einziges Argument erhält. Für uns ist unsere Erfolgs-Callback-Funktion die FunktiondisplayLocation.error: [optional] Dies ist eine Callback-Funktion, die einPositionErrorals einziges Eingabeparameter erhält. Mehr dazu können Sie hier lesen. Unsere Fehler-Callback-Funktion ist die FunktionshowError.options: [optional] Dies ist ein Objekt, das dieoptionsEigenschaft beschreibt, die an die MethodegetCurrentPositionübergeben werden soll. Mehr dazu können Sie hier lesen. Unser Optionen-Parameter ist dasoptions-Objekt.
Bevor wir unsere Funktion displayLocation schreiben, kümmern wir uns um die Funktion showError und das Objekt options.
// Displays the different error messages
showError = (error) => {
mapArea.style.display = "block"
switch (error.code) {
case error.PERMISSION_DENIED:
mapArea.innerHTML = "You denied the request for your location."
break;
case error.POSITION_UNAVAILABLE:
mapArea.innerHTML = "Your Location information is unavailable."
break;
case error.TIMEOUT:
mapArea.innerHTML = "Your request timed out. Please try again"
break;
case error.UNKNOWN_ERROR:
mapArea.innerHTML = "An unknown error occurred please try again after some time."
break;
}
}
//Makes sure location accuracy is high
const options = {
enableHighAccuracy: true
}
Schreiben wir nun den Code für unsere Funktion displayLocation innerhalb unserer Datei main.js.
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
}
Wir haben jetzt den Breiten- und Längengrad unseres Benutzers und können sie in der Konsole anzeigen, indem wir den folgenden Code in displayLocation schreiben:
console.log( `Current Latitude is ${lat} and your longitude is ${lng}` );
Schritt 3: Den aktuellen Standort des Benutzers auf einer Google Map anzeigen
Um dies zu tun, werden wir diese Codezeilen zu unserer Funktion displayLocation hinzufügen:
const latlng = {lat, lng}
showMap(latlng);
createMarker(latlng);
mapArea.style.display = "block";
Die erste Zeile nimmt unsere `lat`- und `lng`-Werte und kapselt sie im `latlng`-Objekt-Literal. Dies erleichtert uns die Verwendung in unserer App.
Die zweite Codezeile ruft eine Funktion showMap auf, die ein latlng-Argument akzeptiert. Hier können wir unsere Google Map instanziieren und sie in unserer Benutzeroberfläche rendern.
Die dritte Zeile ruft eine Funktion createMarker auf, die ebenfalls unser Objekt-Literal (latlng) als Argument entgegennimmt und es verwendet, um einen Google Maps-Marker für uns zu erstellen.
Die vierte Zeile macht den `mapArea` sichtbar, damit unser Benutzer den Standort nun sehen kann.
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const latlng = { lat, lng }
showMap(latlng);
createMarker(latlng);
mapArea.style.display = "block";
}
Nun erstellen wir unsere Funktionen. Wir beginnen mit der Funktion showMap.
showMap = (latlng) => {
let mapOptions = {
center: latlng,
zoom: 17
};
Gmap = new google.maps.Map(mapArea, mapOptions);
}
Die Funktion showMap erstellt ein Objekt `mapOptions`, das die Kartenmitte (die Breiten- und Längengradkoordinaten, die wir von `displayLocation` erhalten haben) und den Zoomlevel der Karte enthält. Schließlich erstellen wir eine Instanz der Google Maps-Klasse und übergeben sie an unsere Karte. In wenigen Worten: Wir instanziieren die Google Maps-Klasse.
Um eine Karteninstanz zu erstellen, geben wir zwei Parameter im Konstruktor an: das `div`, in dem die Karte angezeigt werden soll, und die `mapOptions`. In unserem Fall heißt unser Div `mapArea` und unsere `mapOptions` heißt `mapOptions`. Danach wird unsere erstellte Karte angezeigt, aber ohne Marker. Wir brauchen einen Marker, damit der Benutzer seine aktuelle Position auf der Karte identifizieren kann.
Erstellen wir unseren Marker mit der Funktion createMarker:
createMarker = (latlng) => {
let markerOptions = {
position: latlng,
map: Gmap,
animation: google.maps.Animation.BOUNCE,
clickable: true
};
Gmarker = new google.maps.Marker(markerOptions);
}
Ein paar Dinge, die in diesem Code zu beachten sind:
- Die Eigenschaft `position` positioniert den Marker am angegebenen `latlng`.
- Die Eigenschaft `map` gibt die Karteninstanz an, auf der der Marker gerendert werden soll (in unserem Fall ist es `Gmap`).
- Die Eigenschaft `animation` fügt unserem Marker ein kleines `BOUNCE` hinzu.
- Die Eigenschaft `clickable` auf `true` gesetzt bedeutet, dass unser Marker angeklickt werden kann.
- Schließlich instanziieren wir die Marker-Klasse in unserer `Gmarker`-Instanzvariable.
Bisher wurde der Standort unseres Benutzers abgerufen, die Karte wurde gerendert und der Benutzer kann seinen aktuellen Standort auf der Karte sehen. Die Dinge sehen gut aus! 🕺

Schritt 4: Breiten- und Längengrad an die Geocoding API übergeben
Die Geocoding API von Google wird verwendet, um die numerischen geografischen Koordinaten unseres Benutzers mithilfe des zuvor behandelten Reverse-Geocoding-Prozesses in eine formatierte, menschenlesbare Adresse umzuwandeln.
Die URL hat dieses Format:
https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters
...wobei das outputFormat entweder json oder xml sein kann, was das Format bestimmt, in dem die Daten geliefert werden. Der Teil parameters ist eine Liste von Parametern, die für die Anfrage benötigt werden.
Unsere Anfrage-URL wird so aussehen:
https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=${__KEY}
Lassen Sie uns nun die Verbindung zur API herstellen. Dies würden wir in einer Funktion namens getGeolocation tun.
getGeolocation = (lat, lng) => {
const latlng = lat + "," + lng;
fetch( `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=${__KEY}` )
.then(res => res.json())
.then(data => console.log(data.results));
}
Die Funktion getGeolocation nimmt zwei Argumente (lat und lng), verkettet sie zu einer neuen latlng-Variable, die an die URL übergeben wird.
Mithilfe der Fetch API (mehr dazu hier) fügen wir die neue latlng und __KEY in die Geocoding-Anfrage-URL ein. Dann übergeben wir auf dem Antwortobjekt, das wir erhalten, die Methode .json, um das Promise mit JSON aufzulösen. Schließlich protokollieren wir die Antwort in unserer Konsole.
Um unsere neu erstellte Funktion zu nutzen, müssen wir sie in der Funktion displayLocation aufrufen. Aktualisieren wir also unsere Funktion displayLocation, damit sie den Aufruf der Funktion getGeolocation enthält:
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const latlng = { lat, lng }
showMap(latlng);
createMarker(latlng);
mapArea.style.display = "block";
getGeolocation(lat, lng)// our new function call
}
Die zurückgegebenen Daten sollten in etwa so aussehen:
{
"results" :
{
"address_components":
{
"long_name": "1600",
"short_name": "1600",
"types": ["street_number"]
},
{
"long_name": "Amphitheatre Pkwy",
"short_name": "Amphitheatre Pkwy",
"types": ["route"]
},
{
"long_name": "Mountain View",
"short_name": "Mountain View",
"types": ["locality", "political"]
},
{
"long_name": "Santa Clara County",
"short_name": "Santa Clara County",
"types": ["administrative_area_level_2", "political"]
},
{
"long_name": "California",
"short_name": "CA",
"types": ["administrative_area_level_1", "political"]
},
{
"long_name": "United States",
"short_name": "US",
"types": ["country", "political"]
},
{
"long_name": "94043",
"short_name": "94043",
"types": ["postal_code"]
}
],
"formatted_address": "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
"geometry": {
"location": {
"lat": 37.4224764,
"lng": -122.0842499
},
"location_type": "ROOFTOP",
"viewport": {
"northeast": {
"lat": 37.4238253802915,
"lng": -122.0829009197085
},
"southwest": {
"lat": 37.4211274197085,
"lng": -122.0855988802915
}
}
},
"place_id": "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"types": ["street_address"]
}
],
"status" : "OK"
}
Schritt 5: Die zurückgegebenen Adressen dem Benutzer zur Auswahl anzeigen
An diesem Punkt haben wir eine Anfrage an die Google Geocoding API gesendet und unser Ergebnis in der Konsole protokolliert. Nun müssen wir die Ergebnisse in einer Benutzeroberfläche für unseren Benutzer anzeigen. Dies erfordert zwei Dinge:
- Erstellen Sie eine neue Funktion, die die Erstellung von HTML-Elementen handhabt.
- Aktualisieren Sie unsere Funktion
getGeolocation, um den Funktionsaufruf zu tätigen.
Erstellen wir die Funktion, die sich um die Erstellung der HTML-Elemente und die Aktualisierung des DOM kümmert.
populateCard = (geoResults) => {
geoResults.map(geoResult => {
// first create the input div container
const addressCard = document.createElement('div');
// then create the input and label elements
const input = document.createElement('input');
const label = document.createElement('label');
// then add materialize classes to the div and input
addressCard.classList.add("card");
input.classList.add("with-gap");
// add attributes to them
label.setAttribute("for", geoResult.place_id);
label.innerHTML = geoResult.formatted_address;
input.setAttribute("name", "address");
input.setAttribute("type", "radio");
input.setAttribute("value", geoResult.formatted_address);
input.setAttribute("id", geoResult.place_id);
addressCard.appendChild(input);
addressCard.appendChild(label)
return (
// append the created div to the locationsAvailable div
locationsAvailable.appendChild(addressCard)
);
})
}
In dieser Funktion iterieren wir durch unsere Ergebnisse und erstellen einige HTML-Elemente (div, input und ein label), hängen das input und das label an das div und hängen schließlich das neue div an ein übergeordnetes div (welches locationsAvailable ist). Sobald wir das Ergebnis von unserem API-Aufruf erhalten, wird unser DOM erstellt und dem Benutzer angezeigt.
Als nächstes aktualisieren wir unsere Funktion getGeolocation, um unsere Funktion populateCard aufzurufen, indem wir die letzte Zeile von getGeolocation durch diese ersetzen:
.then(data => populateCard(data.results));
...was bedeutet, dass unsere aktualisierte Funktion so aussehen sollte:
getGeolocation = (lat, lng) => {
const latlng = lat + "," + lng;
fetch( `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=${__KEY}` )
.then(res => res.json())
.then(data => populateCard(data.results));
}
An diesem Punkt sollte alles einwandfrei funktionieren. Unser Benutzer klickt auf einen Button, erhält einen Standort, der auf der Karte angezeigt wird, zusammen mit einer Liste von Adressen, die dem aktuellen Standort entsprechen.

Schritt 6: Auf Kartenereignisse hören und Schritte 4 und 5 wiederholen
Wenn unser Benutzer beschließt, die Karte oder den Marker zu verschieben, passiert nichts mit der Benutzeroberfläche — es werden keine neuen Adressen angezeigt und alles bleibt statisch. Wir müssen das beheben, also machen wir unsere App dynamisch, indem wir auf Kartenereignisse hören. Alles über Google Map Events können Sie hier lesen.
Es gibt drei Ereignisse, auf die wir hören wollen:
drag: Dies wird ausgelöst, sobald der Benutzer beginnt, die Karte zu ziehen und sie weiter zieht.dragend: Dies wird ausgelöst, sobald der Benutzer aufhört, die Karte zu ziehen.idle: Dies wird ausgelöst, sobald jedes Ereignis ausgelöst wurde und die Karte inaktiv ist.
Schnelle Frage: Warum sind diese Ereignisse am besten für unsere App geeignet?
Schnelle Antwort: Die ersten beiden Ereignisse stellen sicher, dass unser Kartenmarker während des Zieh-Ereignisses in der Mitte der Karte bleibt, während das Idle-Ereignis eine Geocoding-Anfrage mit den neuen Koordinaten auslöst.
Um auf diese Ereignisse zu hören, müssen wir die Funktion showMap mit Folgendem aktualisieren:
Gmap.addListener('drag', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('dragend', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('idle', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
if (Gmarker.getPosition().lat() !== lat || Gmarker.getPosition().lng() !== lng) {
setTimeout(() => {
updatePosition(this.getCenter().lat(), this.getCenter().lng()); // update position display
}, 2000);
}
});
Wie oben erläutert, stellen die ersten beiden Ereignis-Listener sicher, dass der Marker in der Mitte unserer Karte bleibt. Achten Sie besonders auf den idle-Ereignis-Listener, denn dort geschieht die eigentliche Arbeit.
Sobald das Idle-Ereignis ausgelöst wird, wandert der Marker zur Mitte, dann wird geprüft, ob die aktuelle Position des Markers mit den Breiten- oder Längengradwerten, die von der Funktion displayLocation empfangen wurden, übereinstimmt. Wenn dies nicht der Fall ist, rufen wir die Funktion updatePosition nach zwei Sekunden Inaktivität auf.
Da wir dies gesagt haben, müssen wir die Funktion showMap einige Aktualisierungen vornehmen. Erstens müssen wir auf der Funktionsüberschrift weitere Parameter aufnehmen und im Aufruf der Funktion showMap müssen wir dort auch die neuen Argumente hinzufügen. Unsere Funktion showMap sollte wie folgt aussehen:
showMap = (latlng, lat, lng) => {
let mapOptions = {
center: latlng,
zoom: 17
};
Gmap = new google.maps.Map(mapArea, mapOptions);
Gmap.addListener('drag', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('dragend', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('idle', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
if (Gmarker.getPosition().lat() !== lat || Gmarker.getPosition().lng() !== lng) {
setTimeout(() => {
updatePosition(this.getCenter().lat(), this.getCenter().lng()); // update position display
}, 2000);
}
});
}
Und unsere Funktion displayLocation sollte wie folgt aussehen:
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const latlng = { lat, lng }
showMap(latlng, lat, lng); //passed lat and lng as the new arguments to the function
createMarker(latlng);
mapArea.style.display = "block";
getGeolocation(lat, lng);
}
Nachdem wir auf die Kartenereignisse gehört haben, wiederholen wir Schritt 4 und Schritt 5.
Wir beginnen mit dem Schreiben unserer Funktion updatePosition. Diese Funktion führt vorerst nur eine Aktion aus, nämlich die Übergabe der neuen Breiten- und Längengradwerte an die Funktion getGeolocation.
updatePosition = (lat, lng) => {
getGeolocation(lat, lng);
}
Nachdem die neue Position ermittelt und Adressen abgerufen wurden, sollte sich unser DOM für den Benutzer neu rendern, richtig? Nun, das tut es nicht. Und um das zu beheben, erstellen wir eine Funktion, die das DOM zum Neu rendern zwingt.
// check if the container has a child node to force re-render of dom
function removeAddressCards(){
if (locationsAvailable.hasChildNodes()) {
while (locationsAvailable.firstChild) {
locationsAvailable.removeChild(locationsAvailable.firstChild);
}
}
}
Sie prüft, ob das locationsAvailable div childNodes hat, und wenn ja, löscht sie diese, bevor neue Adresskarten erstellt werden. Die Funktion populateCard ist nun wie folgt aktualisiert:
populateCard = (geoResults) => {
// check if a the container has a child node to force re-render of dom
removeAddressCards();
geoResults.map(geoResult => {
// first create the input div container
const addressCard = document.createElement('div');
// then create the input and label elements
const input = document.createElement('input');
const label = document.createElement('label');
// then add materialize classes to the div and input
addressCard.classList.add("card");
input.classList.add("with-gap");
// add attributes to them
label.setAttribute("for", geoResult.place_id);
label.innerHTML = geoResult.formatted_address;
input.setAttribute("name", "address");
input.setAttribute("type", "radio");
input.setAttribute("value", geoResult.formatted_address);
input.setAttribute("id", geoResult.place_id);
addressCard.appendChild(input);
addressCard.appendChild(label);
return (
locationsAvailable.appendChild(addressCard);
);
})
}
Wir sind fertig und können nun die Adresse des Benutzers vollständig abrufen und anzeigen!
Schritt 7: Das Formular mit den vom Benutzer ausgewählten Adressdaten vorausfüllen
Der letzte Schritt ist das Ausfüllen des Formulars mit der vom Benutzer ausgewählten Adresse. Wir müssen einen Click-Event-Listener zum Adresskarten-Element hinzufügen und die Adresse als Argument an die Callback-Funktion übergeben.
Hier fügen wir den Event-Listener in der Funktion populateCard hinzu:
input.addEventListener('click', () => inputClicked(geoResult));
Sie sollten beachten, dass das Argument `geoResult` im obigen Callback das ausgewählte Adress-Objekt aus dem `results`-Array ist. Das gesagt, aktualisieren Sie die Funktion populateCard, um unseren neuen Code aufzunehmen.
Die Funktion inputClicked verwendet eine Reihe von `if`-Anweisungen, um Werte unseren Formularfeldern zuzuweisen. Bevor wir uns also damit befassen, holen wir unsere Formularfelder ins Spiel:
const inputAddress = document.getElementById('address'),
inputLocality = document.getElementById('locality'),
inputPostalCode = document.getElementById('postal_code'),
inputLandmark = document.getElementById('landmark'),
inputCity = document.getElementById('city'),
inputState = document.getElementById('state');
Nachdem wir dies getan haben, widmen wir uns nun dem Vorausfüllen des Formulars mit den `address_components` in der Funktion inputClicked.
inputClicked = result => {
result.address_components.map(component => {
const types = component.types
if (types.includes('postal_code')) {
inputPostalCode.value = component.long_name
}
if (types.includes('locality')) {
inputLocality.value = component.long_name
}
if (types.includes('administrative_area_level_2')) {
inputCity.value = component.long_name
}
if (types.includes('administrative_area_level_1')) {
inputState.value = component.long_name
}
if (types.includes('point_of_interest')) {
inputLandmark.value = component.long_name
}
});
inputAddress.value = result.formatted_address;
// to avoid labels overlapping pre-filled input contents
M.updateTextFields();
// removes the address cards from the UI
removeAddressCards();
}
Der obige Codeblock iteriert über die geklickte (oder ausgewählte) Adresskomponente, prüft die Typen der Komponenten und weist sie dann den Eingabefeldern zu, wenn sie übereinstimmen.

Die Funktion M.updateTextFields() stammt von Materialize und stellt sicher, dass das Label nicht mit den Werten der Eingabefelder überlappt, und die Funktion removeAddressCards() entfernt die Adresskarten aus der Benutzeroberfläche.
Damit sind wir mit unserer App fertig und haben unseren Benutzern viel Tipparbeit und Kopfzerbrechen erspart! Sicherlich werden sie uns für die Implementierung einer so problemlosen Lösung danken.
Dieses gesamte UX-Experiment kann als Abkürzung betrachtet werden, die dem Benutzer hilft, das Versandadressformular vorauszufüllen. Wir sollten hier klar darauf hinweisen, dass die zurückgegebenen Adressen nicht immer 100% korrekt sind. Aber deshalb erlauben wir, dass die Adresse im UI manuell bearbeitet werden kann.
Demo!
Sehen Sie den Pen Prefill Address Form with Geolocation and Google Maps von CSS-Tricks (@css-tricks) auf CodePen.
Gute Idee, aber eine Warnung: Wenn Sie Kunden in der EU haben, können Sie diesen Ansatz dank der DSGVO wahrscheinlich vergessen, da eine Übertragung von Standortdaten des Benutzers an Google Maps schwer zu rechtfertigen ist, da sie für die Bereitstellung des Dienstes nicht notwendig ist. (Sie könnten den Benutzer um Zustimmung bitten, aber das eröffnet eine ganz andere Büchse der Pandora, da Zustimmung widerrufen werden kann, was Sie dazu verpflichtet, sicherzustellen, dass Google diese von Ihnen übertragenen Standortdaten löscht.)
Die Daten sind anonym und flüchtig. Ein gut formulierte paar Sätze würden ausreichen. Die einzige Information, die Sie speichern, ist ihre Adresse, die unter die Erfüllung eines Vertrags fällt.
Wenn ich die Demo auf dieser Seite ausführe, erhalte ich die Meldung „Sie haben die Anfrage nach Ihrem Standort abgelehnt.“ Meine Browsereinstellung (Chrome) für Standortberechtigungen lautet „Vor dem Zugriff fragen“, aber es wird niemals nach einer Berechtigung gefragt. Wenn ich die Demo direkt auf CodePen versuche, gibt es die Meldung nicht aus, aber es zeigt auch nie eine Kartenoberfläche.
Das liegt daran, dass es sich in einem iFrame befindet… öffnen Sie es in einem neuen Tab.
https://codepen.io/team/css-tricks/full/XBmazq/
Das war interessant – als ich mein Browserfenster maximiert hatte UND es dann mit „codepen.io möchte Ihren Standort wissen“ aufploppte, funktionierte es danach OK. Interessant.
getLocation, displayLocation und showMap scheinen implizite Globale zu sein.
Sieht gut aus, funktioniert aber nur, wenn man von zu Hause einkauft, die meisten Leute kaufen aber bei der Arbeit ein. :-p
Ich liebe diese Idee. Aber eine Erinnerung daran, dass Geolocation je nach Netzwerk und Art des Geräts sehr unzuverlässig sein kann und den Benutzer noch mehr verwirren kann, wenn der Pin nicht genau ist. Ich habe gerade die Codepen-Demo getestet und auch wenn ich in einer ziemlich dichten Stadt bin, war der Standort etwa eine halbe Meile daneben. Das funktioniert wahrscheinlich gut auf GPS-fähigen Geräten. Aber Netzwerk-Geolocation, nicht so sehr.
Ich habe die Codepen-Demo auf Windows 10 64 Bit getestet. Ich lebe in der Stadt Leuven, Belgien.
IE11: Codepen unterstützt IE11 nicht. Das HTML konnte im „Debug“-Modus gerendert werden, aber es tat nicht viel.
Chrome: Ausgezeichnet! Chrome hat mich gefragt, ob ich die Standortabfrage zulassen möchte. Als ich zugestimmt habe, wurde mir die Adresse eines Nachbarn (etwa 15 Meter entfernt) angezeigt.
Edge: Ich habe den Test abgebrochen. Es scheint, dass die Zustimmung von Edge zur Nutzung von Standortdiensten einen mühsamen Weg durch die Windows-Einstellungen bedeuten würde.