Einfache Filialsuche mit der Google Maps Platform erstellen (JavaScript)

1. Hinweis

Eine der häufigsten Funktionen einer Website ist die Anzeige einer Google-Karte, auf der ein oder mehrere Standorte für ein Unternehmen, eine Einrichtung oder eine andere Einheit mit physischer Präsenz hervorgehoben werden. Die Implementierung dieser Karten kann je nach Anforderungen stark variieren, z. B. in Bezug auf die Anzahl der Standorte und die Häufigkeit, mit der sie sich ändern.

In diesem Codelab sehen Sie sich den einfachsten Anwendungsfall an: eine kleine Anzahl von Standorten, die sich selten ändern, z. B. eine Filialsuche für ein Unternehmen mit einer Kette von Geschäften. In diesem Fall können Sie einen relativ einfachen Ansatz ohne serverseitige Programmierung verwenden. Das bedeutet aber nicht, dass Sie nicht kreativ werden können. Sie können das GeoJSON-Datenformat verwenden, um beliebige Informationen zu jedem Geschäft auf Ihrer Karte zu speichern und zu rendern. Außerdem können Sie die Markierungen und den allgemeinen Stil der Karte anpassen.

Als zusätzlichen Bonus verwenden Sie Cloud Shell, um die Standortsuche zu entwickeln und zu hosten. Die Verwendung dieses Tools ist zwar nicht zwingend erforderlich, ermöglicht es Ihnen jedoch, die Shopsuche auf jedem Gerät mit einem Webbrowser zu entwickeln und sie öffentlich online verfügbar zu machen.

489628918395c3d0.png

Voraussetzungen

  • Grundkenntnisse in HTML und JavaScript

Aufgabe

  • Eine Karte mit einer Reihe von Filialstandorten und Informationen anzeigen, die im GeoJSON-Format gespeichert sind.
  • Markierungen und die Karte selbst anpassen
  • Zusätzliche Informationen zum Geschäft anzeigen, wenn auf die Markierung geklickt wird
  • Fügen Sie der Webseite eine Place Autocomplete-Suchleiste hinzu.
  • Den nächstgelegenen Filialstandort für einen vom Nutzer angegebenen Ausgangspunkt ermitteln.

2. Einrichten

Aktivieren Sie in Schritt 3 des folgenden Abschnitts die folgenden drei APIs für dieses Codelab:

  • Maps JavaScript API
  • Places API
  • Distance Matrix API

Einstieg in die Google Maps Platform

Wenn Sie die Google Maps Platform noch nicht verwendet haben, folgen Sie der Anleitung für die ersten Schritte mit der Google Maps Platform oder sehen Sie sich die Playlist „Erste Schritte mit der Google Maps Platform“ an, um die folgenden Schritte auszuführen:

  1. Erstellen Sie ein Rechnungskonto.
  2. Projekt erstellen
  3. Aktivieren Sie die APIs und SDKs der Google Maps Platform, die im vorherigen Abschnitt aufgeführt sind.
  4. Generieren Sie einen API-Schlüssel.

Cloud Shell aktivieren

In diesem Codelab verwenden Sie Cloud Shell, eine Befehlszeilenumgebung, die in Google Cloud ausgeführt wird und Zugriff auf Produkte und Ressourcen bietet, die in Google Cloud ausgeführt werden. So können Sie Ihr Projekt vollständig über Ihren Webbrowser hosten und ausführen.

Klicken Sie zum Aktivieren von Cloud Shell in der Cloud Console auf Cloud Shell aktivieren 89665d8d348105cd.png. Es dauert nur wenige Augenblicke, bis die Umgebung bereitgestellt und eine Verbindung hergestellt wird.

5f504766b9b3be17.png

Dadurch wird im unteren Bereich Ihres Browsers eine neue Shell geöffnet. Möglicherweise wird vorher ein Einführungs-Interstitial angezeigt.

d3bb67d514893d1f.png

Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und das Projekt bereits auf die Projekt-ID eingestellt ist, die Sie bei der Einrichtung ausgewählt haben.

$ gcloud auth list
Credentialed Accounts:
ACTIVE  ACCOUNT
  *     <myaccount>@<mydomain>.com
$ gcloud config list project
[core]
project = <YOUR_PROJECT_ID>

Wenn das Projekt aus irgendeinem Grund nicht festgelegt ist, führen Sie den folgenden Befehl aus:

$ gcloud config set project <YOUR_PROJECT_ID>

3. „Hallo Welt!“ mit einer Karte

Mit der Entwicklung einer Karte beginnen

Erstellen Sie in Cloud Shell zuerst eine HTML-Seite, die als Grundlage für den Rest des Codelabs dient.

  1. Klicken Sie in der Symbolleiste von Cloud Shell auf Editor starten 996514928389de40.png, um einen Code-Editor auf einem neuen Tab zu öffnen.

Mit diesem webbasierten Code-Editor können Sie Dateien in Cloud Shell ganz einfach bearbeiten.

Screen Shot 2017-04-19 at 10.22.48 AM.png

  1. Erstellen Sie im Code-Editor ein neues store-locator-Verzeichnis für Ihre App. Klicken Sie dazu auf Datei > Neuer Ordner.

NewFolder.png

  1. Geben Sie dem neuen Ordner den Namen store-locator.

Als Nächstes erstellen Sie eine Webseite mit einer Karte.

  1. Erstellen Sie im Verzeichnis store-locator eine Datei mit dem Namen index.html.

3c257603da5ab524.png

  1. Fügen Sie der Datei index.html den folgenden Inhalt hinzu:

index.html

<html>

<head>
    <title>Store Locator</title>
    <style>
        #map {
            height: 100%;
        }
        
        html,
        body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <!-- The div to hold the map -->
    <div id="map"></div>

    <script src="app.js"></script>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap&solution_channel=GMP_codelabs_simplestorelocator_v1_a">
    </script>
</body>

</html>

Dies ist die HTML-Seite, auf der die Karte angezeigt wird. Sie enthält CSS, damit die Karte die gesamte Seite einnimmt, ein <div>-Tag für die Karte und ein <script>-Tag-Paar. Mit dem ersten Script-Tag wird eine JavaScript-Datei namens app.js geladen, die den gesamten JavaScript-Code enthält. Mit dem zweiten Script-Tag wird der API-Schlüssel geladen. Außerdem wird die Places Library für die automatische Vervollständigung verwendet, die Sie später hinzufügen, und der Name der JavaScript-Funktion angegeben, die ausgeführt wird, sobald die Maps JavaScript API geladen ist, nämlich initMap.

  1. Ersetzen Sie den Text YOUR_API_KEY im Code-Snippet durch den API-Schlüssel, den Sie zuvor in diesem Codelab generiert haben.
  2. Erstellen Sie schließlich eine weitere Datei mit dem Namen app.js und dem folgenden Code:

app.js

function initMap() {
   // Create the map.
    const map = new google.maps.Map(document.getElementById('map'), {
        zoom: 7,
        center: { lat: 52.632469, lng: -1.689423 },
    });

}

Das ist der Mindestcode, der zum Erstellen einer Karte erforderlich ist. Sie übergeben einen Verweis auf das <div>-Tag, in dem die Karte angezeigt werden soll, und geben den Mittelpunkt und den Zoomfaktor an.

Wenn Sie diese App testen möchten, können Sie den einfachen Python-HTTP-Server in Cloud Shell ausführen.

  1. Rufen Sie Cloud Shell auf und geben Sie Folgendes ein:
$ cd store-locator
$ python3 -m http.server 8080

Sie sehen einige Zeilen mit Logausgabe, die zeigen, dass Sie den einfachen HTTP-Server in Cloud Shell ausführen und die Webanwendung den Localhost-Port 8080 überwacht.

  1. Öffnen Sie einen Webbrowser-Tab für diese App, indem Sie in der Cloud Console-Symbolleiste auf Webvorschau95e419ae763a1d48.png klicken und Vorschau auf Port 8080 auswählen.

47b06e5169eb5add.png

bdab1f021a3b91d5.png

Wenn Sie auf dieses Menüelement klicken, wird in Ihrem Webbrowser ein neuer Tab mit dem Inhalt des HTML-Codes geöffnet, der vom einfachen Python-HTTP-Server bereitgestellt wird. Wenn alles funktioniert hat, sollte eine Karte mit London, England, im Mittelpunkt angezeigt werden.

Drücken Sie in Cloud Shell Control+C, um den einfachen HTTP-Server zu beenden.

4. Karte mit GeoJSON-Daten füllen

Sehen Sie sich nun die Daten für die Geschäfte an. GeoJSON ist ein Datenformat, das einfache geografische Objekte wie Punkte, Linien oder Polygone auf einer Karte darstellt. Die Funktionen können auch beliebige Daten enthalten. GeoJSON eignet sich daher hervorragend für die Darstellung der Geschäfte, die im Wesentlichen Punkte auf einer Karte mit einigen zusätzlichen Daten wie Name, Öffnungszeiten und Telefonnummer des Geschäfts sind. Vor allem wird GeoJSON in Google Maps unterstützt. Sie können also ein GeoJSON-Dokument an eine Google-Karte senden und es wird entsprechend auf der Karte gerendert.

  1. Erstellen Sie eine neue Datei mit dem Namen stores.json und fügen Sie den folgenden Code ein:

stores.json

{
    "type": "FeatureCollection",
    "features": [{
            "geometry": {
                "type": "Point",
                "coordinates": [-0.1428115,
                    51.5125168
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Modern twists on classic pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Mayfair",
                "phone": "+44 20 1234 5678",
                "storeid": "01"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-2.579623,
                    51.452251
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Come and try our award-winning cakes and pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Bristol",
                "phone": "+44 117 121 2121",
                "storeid": "02"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    1.273459,
                    52.638072
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Whatever the occasion, whether it's a birthday or a wedding, Josie's Patisserie has the perfect treat for you. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Norwich",
                "phone": "+44 1603 123456",
                "storeid": "03"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-1.9912838,
                    50.8000418
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "A gourmet patisserie that will delight your senses. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Wimborne",
                "phone": "+44 1202 343434",
                "storeid": "04"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-2.985933,
                    53.408899
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Spoil yourself or someone special with our classic pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Liverpool",
                "phone": "+44 151 444 4444",
                "storeid": "05"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-1.689423,
                    52.632469
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Come and feast your eyes and tastebuds on our delicious pastries and cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Tamworth",
                "phone": "+44 5555 55555",
                "storeid": "06"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-3.155305,
                    51.479756
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Josie's Patisserie is family-owned, and our delectable pastries, cakes, and great coffee are renowed. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Cardiff",
                "phone": "+44 29 6666 6666",
                "storeid": "07"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-0.725019,
                    52.668891
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Oakham's favorite spot for fresh coffee and delicious cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Oakham",
                "phone": "+44 7777 777777",
                "storeid": "08"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-2.477653,
                    53.735405
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Enjoy freshly brewed coffe, and home baked cakes in our homely cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Blackburn",
                "phone": "+44 8888 88888",
                "storeid": "09"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-0.211363,
                    51.108966
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "A delicious array of pastries with many flavours, and fresh coffee in an snug cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Crawley",
                "phone": "+44 1010 101010",
                "storeid": "10"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-0.123559,
                    50.832679
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Grab a freshly brewed coffee, a decadent cake and relax in our idyllic cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Brighton",
                "phone": "+44 1313 131313",
                "storeid": "11"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-3.319575,
                    52.517827
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Come in and unwind at this idyllic cafe with fresh coffee and home made cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Newtown",
                "phone": "+44 1414 141414",
                "storeid": "12"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    1.158167,
                    52.071634
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Fresh coffee and delicious cakes in an snug cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Ipswich",
                "phone": "+44 1717 17171",
                "storeid": "13"
            }
        }
    ]
}

Das sind viele Daten, aber wenn Sie sie sich ansehen, stellen Sie fest, dass es sich einfach um dieselbe Struktur handelt, die für jedes Geschäft wiederholt wird. Jedes Geschäft wird als GeoJSON-Point mit seinen Koordinaten und den zusätzlichen Daten unter dem Schlüssel properties dargestellt. Interessanterweise können in GeoJSON unter dem Schlüssel properties beliebig benannte Schlüssel enthalten sein. In diesem Codelab sind das die Schlüssel category, hours, description, name und phone.

  1. Bearbeiten Sie nun app.js so, dass das GeoJSON in stores.js auf Ihre Karte geladen wird.

app.js

function initMap() {
  // Create the map.
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: {lat: 52.632469, lng: -1.689423},
  });

  // Load the stores GeoJSON onto the map.
  map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});

  const apiKey = 'YOUR_API_KEY';
  const infoWindow = new google.maps.InfoWindow();

  // Show the information for a store when its marker is clicked.
  map.data.addListener('click', (event) => {
    const category = event.feature.getProperty('category');
    const name = event.feature.getProperty('name');
    const description = event.feature.getProperty('description');
    const hours = event.feature.getProperty('hours');
    const phone = event.feature.getProperty('phone');
    const position = event.feature.getGeometry().get();
    const content = `
      <h2>${name}</h2><p>${description}</p>
      <p><b>Open:</b> ${hours}<br/><b>Phone:</b> ${phone}</p>
    `;

    infoWindow.setContent(content);
    infoWindow.setPosition(position);
    infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
    infoWindow.open(map);
  });
}

Im Codebeispiel haben Sie Ihr GeoJSON auf die Karte geladen, indem Sie loadGeoJson aufgerufen und den Namen der JSON-Datei übergeben haben. Außerdem haben Sie eine Funktion definiert, die jedes Mal ausgeführt wird, wenn auf eine Markierung geklickt wird. Die Funktion kann dann auf die zusätzlichen Daten für das Geschäft zugreifen, dessen Markierung angeklickt wurde, und die Informationen in einem angezeigten Infofenster verwenden. Um diese App zu testen, können Sie den einfachen Python-HTTP-Server mit demselben Befehl wie zuvor ausführen.

  1. Kehren Sie zu Cloud Shell zurück und geben Sie Folgendes ein:
$ python3 -m http.server 8080
  1. Klicken Sie noch einmal auf Webvorschau95e419ae763a1d48.png > Vorschau auf Port 8080. Nun sollte eine Karte mit Markierungen angezeigt werden, auf die Sie klicken können, um Details zu den einzelnen Geschäften aufzurufen, wie im folgenden Beispiel. Fortschritt!

c4507f7d3ea18439.png

5. Karte anpassen

Sie haben es fast geschafft. Sie haben eine Karte mit allen Ihren Geschäftsmarkierungen und zusätzlichen Informationen, die bei einem Klick angezeigt werden. Sie sieht aber aus wie jede andere Google-Karte. Wie langweilig! Mit einem benutzerdefinierten Kartenstil, Markierungen, Logos und Street View-Bildern können Sie die Karte noch interessanter gestalten.

Hier ist eine neue Version von app.js mit benutzerdefiniertem Stil:

app.js

const mapStyle = [{
  'featureType': 'administrative',
  'elementType': 'all',
  'stylers': [{
    'visibility': 'on',
  },
  {
    'lightness': 33,
  },
  ],
},
{
  'featureType': 'landscape',
  'elementType': 'all',
  'stylers': [{
    'color': '#f2e5d4',
  }],
},
{
  'featureType': 'poi.park',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#c5dac6',
  }],
},
{
  'featureType': 'poi.park',
  'elementType': 'labels',
  'stylers': [{
    'visibility': 'on',
  },
  {
    'lightness': 20,
  },
  ],
},
{
  'featureType': 'road',
  'elementType': 'all',
  'stylers': [{
    'lightness': 20,
  }],
},
{
  'featureType': 'road.highway',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#c5c6c6',
  }],
},
{
  'featureType': 'road.arterial',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#e4d7c6',
  }],
},
{
  'featureType': 'road.local',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#fbfaf7',
  }],
},
{
  'featureType': 'water',
  'elementType': 'all',
  'stylers': [{
    'visibility': 'on',
  },
  {
    'color': '#acbcc9',
  },
  ],
},
];

function initMap() {
  // Create the map.
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: {lat: 52.632469, lng: -1.689423},
    styles: mapStyle,
  });

  // Load the stores GeoJSON onto the map.
  map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});

  // Define the custom marker icons, using the store's "category".
  map.data.setStyle((feature) => {
    return {
      icon: {
        url: `img/icon_${feature.getProperty('category')}.png`,
        scaledSize: new google.maps.Size(64, 64),
      },
    };
  });

  const apiKey = 'YOUR_API_KEY';
  const infoWindow = new google.maps.InfoWindow();

  // Show the information for a store when its marker is clicked.
  map.data.addListener('click', (event) => {
    const category = event.feature.getProperty('category');
    const name = event.feature.getProperty('name');
    const description = event.feature.getProperty('description');
    const hours = event.feature.getProperty('hours');
    const phone = event.feature.getProperty('phone');
    const position = event.feature.getGeometry().get();
    const content = `
      <img style="float:left; width:200px; margin-top:30px" src="img/logo_${category}.png">
      <div style="margin-left:220px; margin-bottom:20px;">
        <h2>${name}</h2><p>${description}</p>
        <p><b>Open:</b> ${hours}<br/><b>Phone:</b> ${phone}</p>
        <p><img src="https://maps.googleapis.com/maps/api/streetview?size=350x120&location=${position.lat()},${position.lng()}&key=${apiKey}&solution_channel=GMP_codelabs_simplestorelocator_v1_a"></p>
      </div>
      `;

    infoWindow.setContent(content);
    infoWindow.setPosition(position);
    infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
    infoWindow.open(map);
  });

}

Das haben Sie hinzugefügt:

  • Die Variable mapStyle enthält alle Informationen zum Formatieren der Karte. Als zusätzlichen Bonus können Sie sogar einen eigenen Stil erstellen.
  • Mit der Methode map.data.setStyle haben Sie benutzerdefinierte Markierungen angewendet, für jedes category aus dem GeoJSON eine andere.
  • Sie haben die Variable content so geändert, dass sie ein Logo (wieder mit category aus dem GeoJSON) und ein Street View-Bild für den Standort des Geschäfts enthält.

Bevor Sie die Bereitstellung vornehmen, müssen Sie einige Schritte ausführen:

  1. Legen Sie den richtigen Wert für die Variable apiKey fest, indem Sie den String 'YOUR_API_KEY' in app.js durch Ihren eigenen API-Schlüssel von zuvor ersetzen (denselben, den Sie in index.html eingefügt haben, wobei die Anführungszeichen beibehalten werden).
  2. Führen Sie die folgenden Befehle in Cloud Shell aus, um die Marker- und Logografiken herunterzuladen. Prüfen Sie, ob Sie sich im Verzeichnis store-locator befinden. Verwenden Sie Control+C, um den einfachen HTTP-Server zu beenden, falls er ausgeführt wird.
$ mkdir -p img; cd img
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/icon_cafe.png
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/icon_patisserie.png
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/logo_cafe.png
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/logo_patisserie.png
  1. Sehen Sie sich die fertige Händlersuche mit dem folgenden Befehl an:
$ python3 -m http.server 8080

Wenn Sie die Vorschau neu laden, sollte eine Karte wie diese angezeigt werden, mit benutzerdefiniertem Stil, benutzerdefinierten Markierungsbildern, verbesserter Infofensterformatierung und einem Street View-Bild für jeden Ort:

3d8d13da126021dd.png

6. Nutzereingabe abrufen

Nutzer von Standortfindern möchten in der Regel wissen, welches Geschäft sich am nächsten zu ihnen oder zu einer Adresse befindet, an der sie ihre Reise beginnen möchten. Fügen Sie eine Place Autocomplete-Suchleiste hinzu, damit der Nutzer ganz einfach eine Startadresse eingeben kann. Place Autocomplete bietet eine Funktion zur automatischen Vervollständigung, die der automatischen Vervollständigung in anderen Google-Suchleisten ähnelt. Die Vorschläge sind jedoch alle Orte in der Google Maps Platform.

  1. Kehren Sie zurück zu index.html, um die Formatierung für die Autocomplete-Suchleiste und die zugehörige Seitenleiste mit Ergebnissen hinzuzufügen. Vergessen Sie nicht, Ihren API-Schlüssel zu ersetzen, wenn Sie Ihren alten Code eingefügt haben.

index.html

<html>

<head>
  <title>Store Locator</title>
  <style>
    #map {
      height: 100%;
    }
    
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    /* Styling for Autocomplete search bar */
    #pac-card {
      background-color: #fff;
      border-radius: 2px 0 0 2px;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
      box-sizing: border-box;
      font-family: Roboto;
      margin: 10px 10px 0 0;
      -moz-box-sizing: border-box;
      outline: none;
    }
    
    #pac-container {
      padding-top: 12px;
      padding-bottom: 12px;
      margin-right: 12px;
    }
    
    #pac-input {
      background-color: #fff;
      font-family: Roboto;
      font-size: 15px;
      font-weight: 300;
      margin-left: 12px;
      padding: 0 11px 0 13px;
      text-overflow: ellipsis;
      width: 400px;
    }
    
    #pac-input:focus {
      border-color: #4d90fe;
    }
    
    #title {
      color: #fff;
      background-color: #acbcc9;
      font-size: 18px;
      font-weight: 400;
      padding: 6px 12px;
    }
    
    .hidden {
      display: none;
    }

    /* Styling for an info pane that slides out from the left. 
     * Hidden by default. */
    #panel {
      height: 100%;
      width: null;
      background-color: white;
      position: fixed;
      z-index: 1;
      overflow-x: hidden;
      transition: all .2s ease-out;
    }
    
    .open {
      width: 250px;
    }
    
    .place {
      font-family: 'open sans', arial, sans-serif;
      font-size: 1.2em;
      font-weight: 500;
      margin-block-end: 0px;
      padding-left: 18px;
      padding-right: 18px;
    }
    
    .distanceText {
      color: silver;
      font-family: 'open sans', arial, sans-serif;
      font-size: 1em;
      font-weight: 400;
      margin-block-start: 0.25em;
      padding-left: 18px;
      padding-right: 18px;
    }
  </style>
</head>

<body>
  <!-- The div to hold the map -->
  <div id="map"></div>

  <script src="app.js"></script>
  <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap&solution_channel=GMP_codelabs_simplestorelocator_v1_a">
  </script>
</body>

</html>

Sowohl die Suchleiste für die automatische Vervollständigung als auch das Einblendfeld sind anfangs ausgeblendet, bis sie benötigt werden.

  1. Fügen Sie das Autocomplete-Widget jetzt am Ende der Funktion initMap in app.js ein, direkt vor der schließenden geschweiften Klammer.

app.js

  // Build and add the search bar
  const card = document.createElement('div');
  const titleBar = document.createElement('div');
  const title = document.createElement('div');
  const container = document.createElement('div');
  const input = document.createElement('input');
  const options = {
    types: ['address'],
    componentRestrictions: {country: 'gb'},
  };

  card.setAttribute('id', 'pac-card');
  title.setAttribute('id', 'title');
  title.textContent = 'Find the nearest store';
  titleBar.appendChild(title);
  container.setAttribute('id', 'pac-container');
  input.setAttribute('id', 'pac-input');
  input.setAttribute('type', 'text');
  input.setAttribute('placeholder', 'Enter an address');
  container.appendChild(input);
  card.appendChild(titleBar);
  card.appendChild(container);
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

  // Make the search bar into a Places Autocomplete search bar and select
  // which detail fields should be returned about the place that
  // the user selects from the suggestions.
  const autocomplete = new google.maps.places.Autocomplete(input, options);

  autocomplete.setFields(
      ['address_components', 'geometry', 'name']);

Der Code schränkt die Vorschläge zur automatischen Vervollständigung auf Adressen ein, da Place Autocomplete auch Namen von Einrichtungen und Verwaltungseinheiten zuordnen kann. Außerdem werden nur Adressen im Vereinigten Königreich zurückgegeben. Wenn Sie diese optionalen Angaben hinzufügen, muss der Nutzer weniger Zeichen eingeben, um die Vorhersagen einzugrenzen und die gesuchte Adresse zu finden. Anschließend wird das von Ihnen erstellte Autocomplete div in die rechte obere Ecke der Karte verschoben und angegeben, welche Felder in der Antwort für jeden Ort zurückgegeben werden sollen.

  1. Starten Sie den Server neu und aktualisieren Sie die Vorschau mit dem folgenden Befehl:
$ python3 -m http.server 8080

Rechts oben auf der Karte sollte jetzt ein Autocomplete-Widget angezeigt werden, in dem britische Adressen zu sehen sind, die mit Ihrer Eingabe übereinstimmen.

5163f34a03910187.png

Als Nächstes müssen Sie festlegen, was passieren soll, wenn der Nutzer eine Vorhersage aus dem Widget für die automatische Vervollständigung auswählt. Verwenden Sie diesen Standort dann als Grundlage für die Berechnung der Entfernungen zu Ihren Geschäften.

  1. Fügen Sie am Ende von initMap in app.js nach dem Code, den Sie gerade eingefügt haben, den folgenden Code ein.

app.js

 // Set the origin point when the user selects an address
  const originMarker = new google.maps.Marker({map: map});
  originMarker.setVisible(false);
  let originLocation = map.getCenter();

  autocomplete.addListener('place_changed', async () => {
    originMarker.setVisible(false);
    originLocation = map.getCenter();
    const place = autocomplete.getPlace();

    if (!place.geometry) {
      // User entered the name of a Place that was not suggested and
      // pressed the Enter key, or the Place Details request failed.
      window.alert('No address available for input: \'' + place.name + '\'');
      return;
    }

    // Recenter the map to the selected address
    originLocation = place.geometry.location;
    map.setCenter(originLocation);
    map.setZoom(9);
    console.log(place);

    originMarker.setPosition(originLocation);
    originMarker.setVisible(true);

    // Use the selected address as the origin to calculate distances
    // to each of the store locations
    const rankedStores = await calculateDistances(map.data, originLocation);
    showStoresList(map.data, rankedStores);

    return;
  });

Durch den Code wird ein Listener hinzugefügt, sodass die Karte neu zentriert wird, wenn der Nutzer auf einen der Vorschläge klickt. Der Ursprung wird dann als Grundlage für Ihre Entfernungsberechnungen festgelegt. Die Entfernungsberechnungen implementieren Sie im nächsten Schritt.

7. Nächstgelegene Geschäfte auflisten

Die Directions API funktioniert ähnlich wie das Anfordern einer Wegbeschreibung in der Google Maps App: Sie geben einen einzelnen Start- und Zielort ein, um eine Route zwischen den beiden Orten zu erhalten. Die Distance Matrix API geht noch einen Schritt weiter und ermittelt die optimalen Kombinationen zwischen mehreren möglichen Start- und Zielorten anhand von Reisezeiten und Entfernungen. In diesem Fall geben Sie einen Ursprung und ein Array von Geschäftsstandorten als Ziele an, damit der Nutzer das nächstgelegene Geschäft zur ausgewählten Adresse findet.

  1. Fügen Sie app.js eine neue Funktion namens calculateDistances hinzu.

app.js

async function calculateDistances(data, origin) {
  const stores = [];
  const destinations = [];

  // Build parallel arrays for the store IDs and destinations
  data.forEach((store) => {
    const storeNum = store.getProperty('storeid');
    const storeLoc = store.getGeometry().get();

    stores.push(storeNum);
    destinations.push(storeLoc);
  });

  // Retrieve the distances of each store from the origin
  // The returned list will be in the same order as the destinations list
  const service = new google.maps.DistanceMatrixService();
  const getDistanceMatrix =
    (service, parameters) => new Promise((resolve, reject) => {
      service.getDistanceMatrix(parameters, (response, status) => {
        if (status != google.maps.DistanceMatrixStatus.OK) {
          reject(response);
        } else {
          const distances = [];
          const results = response.rows[0].elements;
          for (let j = 0; j < results.length; j++) {
            const element = results[j];
            const distanceText = element.distance.text;
            const distanceVal = element.distance.value;
            const distanceObject = {
              storeid: stores[j],
              distanceText: distanceText,
              distanceVal: distanceVal,
            };
            distances.push(distanceObject);
          }

          resolve(distances);
        }
      });
    });

  const distancesList = await getDistanceMatrix(service, {
    origins: [origin],
    destinations: destinations,
    travelMode: 'DRIVING',
    unitSystem: google.maps.UnitSystem.METRIC,
  });

  distancesList.sort((first, second) => {
    return first.distanceVal - second.distanceVal;
  });

  return distancesList;
}

Die Funktion ruft die Distance Matrix API mit dem übergebenen Ausgangspunkt als einzelnen Ausgangspunkt und den Filialstandorten als Array von Zielorten auf. Anschließend wird ein Array von Objekten erstellt, in dem die ID des Geschäfts, die Entfernung als menschenlesbarer String und die Entfernung in Metern als numerischer Wert gespeichert werden. Das Array wird dann sortiert.

Der Nutzer erwartet eine Liste der Geschäfte, die nach Entfernung sortiert ist. Füllen Sie für jede Filiale eine Seitenleistenliste mit der Liste aus, die von der Funktion calculateDistances zurückgegeben wird, um die Reihenfolge der Filialen zu bestimmen.

  1. Fügen Sie app.js eine neue Funktion namens showStoresList hinzu.

app.js

function showStoresList(data, stores) {
  if (stores.length == 0) {
    console.log('empty stores');
    return;
  }

  let panel = document.createElement('div');
  // If the panel already exists, use it. Else, create it and add to the page.
  if (document.getElementById('panel')) {
    panel = document.getElementById('panel');
    // If panel is already open, close it
    if (panel.classList.contains('open')) {
      panel.classList.remove('open');
    }
  } else {
    panel.setAttribute('id', 'panel');
    const body = document.body;
    body.insertBefore(panel, body.childNodes[0]);
  }


  // Clear the previous details
  while (panel.lastChild) {
    panel.removeChild(panel.lastChild);
  }

  stores.forEach((store) => {
    // Add store details with text formatting
    const name = document.createElement('p');
    name.classList.add('place');
    const currentStore = data.getFeatureById(store.storeid);
    name.textContent = currentStore.getProperty('name');
    panel.appendChild(name);
    const distanceText = document.createElement('p');
    distanceText.classList.add('distanceText');
    distanceText.textContent = store.distanceText;
    panel.appendChild(distanceText);
  });

  // Open the panel
  panel.classList.add('open');

  return;
}
  1. Starten Sie den Server neu und aktualisieren Sie die Vorschau mit dem folgenden Befehl.
$ python3 -m http.server 8080
  1. Geben Sie schließlich eine Adresse im Vereinigten Königreich in die Suchleiste für die automatische Vervollständigung ein und klicken Sie auf einen der Vorschläge.

Die Karte sollte auf diese Adresse zentriert werden und in der Seitenleiste sollten die Geschäftsstandorte nach Entfernung von der ausgewählten Adresse aufgelistet werden. Ein Beispiel ist unten zu sehen:

489628918395c3d0.png

8. Optional: Webseite hosten

Bisher sehen Sie Ihre Karte nur, wenn Ihr Python-HTTP-Server aktiv ausgeführt wird. Wenn Sie Ihre Karte über Ihre aktive Cloud Shell-Sitzung hinaus ansehen oder die URL Ihrer Karte mit anderen teilen möchten, sollten Sie Cloud Storage zum Hosten Ihrer Webseite verwenden. Cloud Storage ist ein Online-Datenspeicher-Webdienst zum Speichern und Abrufen von Daten in der Infrastruktur von Google. Der Dienst kombiniert die Leistung und Skalierbarkeit von Google Cloud mit erweiterten Sicherheits- und Freigabefunktionen. Außerdem gibt es eine kostenlose Stufe, die sich hervorragend für das Hosting einer einfachen Standortsuche eignet.

In Cloud Storage werden Dateien in Buckets gespeichert, die Ordnern auf Ihrem Computer ähneln. Wenn Sie Ihre Webseite hosten möchten, müssen Sie zuerst einen Bucket erstellen. Sie müssen einen eindeutigen Namen für Ihren Bucket auswählen, z. B. indem Sie Ihren Namen als Teil des Bucket-Namens verwenden.

  1. Wenn Sie sich für einen Namen entschieden haben, führen Sie den folgenden Befehl in Cloud Shell aus:
$ gsutil mb gs://yourname-store-locator

gsutil ist das Tool für die Interaktion mit Cloud Storage. Der Befehl mb steht kreativ für „make bucket“ (Bucket erstellen). Weitere Informationen zu allen verfügbaren Befehlen, einschließlich der von Ihnen verwendeten, finden Sie unter gsutil-Tool.

Standardmäßig sind Ihre in Cloud Storage gehosteten Buckets und Dateien privat. Für Ihre Standortsuche sollen jedoch alle Dateien öffentlich sein, damit sie für alle Nutzer im Internet zugänglich sind. Sie könnten jede Datei nach dem Hochladen öffentlich machen, aber das wäre mühsam. Stattdessen können Sie einfach die Standardzugriffsebene für den Bucket festlegen, den Sie erstellt haben. Alle Dateien, die Sie in den Bucket hochladen, übernehmen diese Zugriffsebene.

  1. Führen Sie den folgenden Befehl aus und ersetzen Sie dabei yourname-store-locator durch den Namen, den Sie für Ihren Bucket ausgewählt haben:
$ gsutil defacl ch -u AllUsers:R gs://yourname-store-locator
  1. Mit dem folgenden Befehl können Sie jetzt alle Dateien im aktuellen Verzeichnis hochladen (derzeit nur die Dateien index.html und app.js):
$ gsutil -h "Cache-Control:no-cache" cp * gs://yourname-store-locator

Sie sollten jetzt eine Webseite mit einer Karte online haben. Die URL zum Aufrufen der Datei lautet http://storage.googleapis.com/yourname-store-locator/index.html. Ersetzen Sie dabei „yourname-store-locator“ durch den Namen des Buckets, den Sie zuvor ausgewählt haben.

Clean-up

Am einfachsten bereinigen Sie alle in diesem Projekt erstellten Ressourcen, indem Sie das Google Cloud-Projekt beenden, das Sie zu Beginn dieser Anleitung erstellt haben:

  • Öffnen Sie in der Cloud Console die Seite „Einstellungen“.
  • Klicken Sie auf Projekt auswählen.
  • Wählen Sie das Projekt aus, das Sie zu Beginn dieser Anleitung erstellt haben, und klicken Sie auf Öffnen.
  • Geben Sie die Projekt-ID ein und klicken Sie auf Beenden.

9. Glückwunsch

Glückwunsch! Sie haben dieses Codelab abgeschlossen.

Das haben Sie gelernt

Weitere Informationen

Welche anderen Codelabs würden Sie sich wünschen?

Datenvisualisierung auf Karten Weitere Informationen zum Anpassen des Stils von Karten 3D-Interaktionen in Karten entwickeln

Ist das gewünschte Codelab oben nicht aufgeführt? Hier können Sie sie mit einem neuen Problem anfordern.

Wenn Sie sich den Code genauer ansehen möchten, finden Sie das Quellcode-Repository unter https://github.com/googlecodelabs/google-maps-simple-store-locator.