Einfache Filialsuche mit Google Maps Platform erstellen (JavaScript)

1. Hinweis

Eine der häufigsten Funktionen einer Website ist die Darstellung einer Google-Karte, auf der ein oder mehrere Standorte für ein Unternehmen, eine Niederlassung oder eine andere juristische Person mit einer physischen Präsenz hervorgehoben sind. Wie diese Karten implementiert werden, ist von den Anforderungen abhängig, z. B. von der Anzahl der Standorte und zur Häufigkeit der Änderungen.

In diesem Codelab sehen Sie sich den einfachsten Anwendungsfall an, also eine kleine Anzahl von Orten, die sich nur selten ändern, z. B. eine Filialsuche für ein Unternehmen mit einer Kette von Geschäften. In diesem Fall können Sie einen relativ niedrigen Ansatz ohne serverseitige Programmierung wählen. Aber das sollten Sie nicht tun: Sie nutzen das GeoJSON-Datenformat, um beliebige Informationen zu jedem Geschäft auf Ihrer Karte zu speichern und zu rendern sowie die Markierungen und den Gesamtstil der Karte selbst anzupassen.

Als besonderen Anreiz verwenden Sie Cloud Shell, um die Filialsuche zu entwickeln und zu hosten. Die Verwendung dieses Tools ist zwar streng erforderlich, aber dadurch können Sie die Filialsuche von jedem Gerät mit einem Webbrowser entwickeln und sie öffentlich verfügbar machen.

489628918395c3d0.png

Voraussetzungen

  • Grundkenntnisse in HTML und JavaScript

Aufgabe

  • Rufen Sie eine Karte mit mehreren Filialstandorten und im GeoJSON-Format gespeicherten Informationen auf.
  • Passen Sie Markierungen und die Karte selbst an.
  • Zusätzliche Informationen zum Shop anzeigen, wenn auf die Markierung geklickt wird
  • Place Autocomplete-Suchleiste auf der Webseite einfügen
  • Ermitteln Sie das Geschäft, das dem vom Nutzer bereitgestellten Ausgangspunkt am nächsten ist.

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

Einführung in Google Maps Platform

Wenn du die Google Maps Platform noch nicht verwendet hast, folge der Einführung in die Google Maps Platform oder folge der Anleitung unter Erste Schritte mit der Google Maps Platform-Playlist.

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

Cloud Shell aktivieren

In diesem Codelab nutzen 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 komplett über Ihren Webbrowser hosten und ausführen.

Klicken Sie auf Cloud Shell aktivieren 89665d8d348105cd, um Cloud Shell über die Cloud Console zu aktivieren. Die Bereitstellung und Verbindung mit der Umgebung dauert nur einen Moment.

5f504766b9b3be17.png

Dadurch wird unter Umständen eine neue Shell im unteren Teil des Browsers geöffnet, in der ein Interstitial eingeblendet wird.

d3bb67d514893d1f.png

Wenn Sie eine Verbindung zu Cloud Shell hergestellt haben, sehen Sie, dass Sie bereits authentifiziert sind und dass das Projekt bereits auf die Projekt-ID gesetzt 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>

Führen Sie den folgenden Befehl aus, wenn das Projekt nicht festgelegt ist:

$ gcloud config set project <YOUR_PROJECT_ID>

3. Hello, World! mit einer Karte

Mit einer Karte entwickeln

In Cloud Shell erstellen Sie 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 in einem neuen Tab zu öffnen.

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

Screenshot 2017-04-19 um 10.22.48.png

  1. Erstellen Sie im Code-Editor ein neues store-locator-Verzeichnis für Ihre App, indem Sie auf File > New Folder klicken.

Neuer Ordner.png

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

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

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

3c257603da5ab524.png

  1. Füge in die Datei index.html Folgendes ein:

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>

Das ist die HTML-Seite, auf der die Karte zu sehen ist. Die Datei enthält CSS, damit die Karte die gesamte Seite einnimmt, ein <div>-Tag für die Karte und zwei <script>-Tags. Das erste Skript-Tag lädt eine JavaScript-Datei namens app.js, die den gesamten JavaScript-Code enthält. Im zweiten Skript-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. Außerdem wird der Name der JavaScript-Funktion angegeben, die ausgeführt wird, sobald die Maps JavaScript API geladen wurde, und zwar initMap.

  1. Ersetzen Sie den Text YOUR_API_KEY im Code-Snippet durch den API-Schlüssel, den Sie zuvor in diesem Codelab erstellt 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 },
    });

}

Dieser Code ist mindestens zum Erstellen einer Karte erforderlich. Sie übergeben einen Verweis zu Ihrem <div>-Tag, um die Karte zu speichern, und geben die Mitte und die Zoomstufe an.

Sie können die Anwendung mit dem einfachen Python-HTTP-Server in Cloud Shell testen.

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

Sie sehen einige Zeilen der Logausgabe, die belegen, dass Sie tatsächlich den einfachen HTTP-Server in Cloud Shell ausführen, wobei die Webanwendung den Localhost-Port 8080 überwacht.

  1. Öffnen Sie in dieser App einen Webbrowser-Tab. Klicken Sie dazu in der Symbolleiste der Cloud Console auf Webvorschau 95e419ae763a1d48 und wählen Sie Vorschau auf Port 8080 aus.

47b06e5169eb5add.png

bdab1f021a3b91d5

Wenn Sie auf diesen Menüpunkt klicken, wird im Browser ein neuer Tab mit dem Inhalt des HTML-Codes geöffnet, der vom einfachen Python-HTTP-Server bereitgestellt wird. Wenn alles gut gelaufen ist, sollte eine Karte mit der Mitte von London angezeigt werden.

Wenn Sie den einfachen HTTP-Server beenden möchten, drücken Sie in Cloud Shell auf Control+C.

4. Karte mit GeoJSON füllen

Sehen Sie sich jetzt die Daten für die Geschäfte an. GeoJSON ist ein Datenformat, das einfache geografische Merkmale wie Punkte, Linien oder Polygone auf einer Karte darstellt. Die Elemente können auch beliebige Daten enthalten. Daher ist GeoJSON ein hervorragender Kandidat für die Darstellung der Geschäfte, die im Wesentlichen Punkte auf einer Karte mit einigen zusätzlichen Daten wie dem Namen des Geschäfts, den Öffnungszeiten und der Telefonnummer sind. Am wichtigsten ist GeoJSON in Google Maps. Sie können also ein GeoJSON-Dokument an eine Google-Karte senden und auf der Karte rendern.

  1. Erstelle eine neue Datei mit dem Namen stores.json und füge 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 ist eine Menge Daten, aber sobald Sie sie nutzen, sehen Sie für alle Geschäfte dieselbe Struktur. Jeder Shop wird als GeoJSON-Point dargestellt, einschließlich der Koordinaten und der zusätzlichen Daten, die im Schlüssel properties enthalten sind. Interessanterweise können mit GeoJSON beliebig beliebige Schlüssel unter dem Schlüssel properties aufgenommen werden. In diesem Codelab sind diese Schlüssel category, hours, description, name und phone.

  1. Bearbeiten Sie jetzt app.js, damit 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 in die Karte geladen, indem Sie loadGeoJson aufgerufen und den Namen der JSON-Datei übergeben haben. Außerdem haben Sie eine Funktion definiert, die bei jedem Klick auf eine Markierung ausgeführt wird. Die Funktion kann dann auf die zusätzlichen Daten für das Geschäft zugreifen, wenn auf die Markierung geklickt wurde. Die Informationen werden dann in einem Infofenster angezeigt. Um diese Anwendung zu testen, können Sie den einfachen Python-HTTP-Server mit dem gleichen 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 Webvorschau 95e419ae763a1d48 & Vorschau auf Port 8080. Nun sollte eine Karte mit Markierungen angezeigt werden, auf die Sie klicken können, um Details zu jedem Geschäft aufzurufen, wie im folgenden Beispiel. Fortschritt!

c4507f7d3ea18439

5. Karte anpassen

Fast geschafft. Sie haben eine Karte mit allen Markierungen für Ihr Geschäft sowie zusätzlichen Informationen angeklickt. Aber es scheint, als hätte jeder Wie stumpf! Mit benutzerdefinierten Kartenstilen, Markierungen, Logos und Street View-Bildern können Sie ihn optimieren.

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);
  });

}

Sie haben Folgendes hinzugefügt:

  • Die Variable mapStyle enthält alle Informationen zum Gestalten von Karten. Wenn Sie möchten, können Sie außerdem einen eigenen Stil erstellen.
  • Mit der Methode map.data.setStyle haben Sie benutzerdefinierte Markierungen angewendet – eine andere für jede category aus dem GeoJSON-Format.
  • Sie haben die Variable content geändert, um ein Logo (noch einmal mit dem category aus dem GeoJSON) und ein Street View-Bild für die Position des Geschäfts hinzuzufügen.

Bevor Sie dies tun, müssen Sie einige Schritte ausführen:

  1. Stelle den korrekten Wert für die apiKey-Variable ein, indem du den 'YOUR_API_KEY'-String in app.js durch deinen eigenen API-Schlüssel aus dem vorherigen Tag austauschst. Den gleichen Schlüssel, den du in index.html eingefügt hast, bleibt in Anführungszeichen.
  2. Führen Sie in Cloud Shell die folgenden Befehle aus, um die Markierungs- und Logografiken herunterzuladen. Achten Sie darauf, dass Sie sich im Verzeichnis store-locator befinden. Mit Control+C können Sie den einfachen HTTP-Server beenden, wenn 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 eine Vorschau der fertigen Filialsuche an. Führen Sie dazu folgenden Befehl aus:
$ python3 -m http.server 8080

Wenn Sie die Vorschau aktualisieren, sollte etwa eine Karte mit benutzerdefinierten Stilen, benutzerdefinierten Markierungsbildern, verbesserten Infofenstern und einem Street View-Bild für jeden Standort angezeigt werden:

3d8d13da126021dd.png

6. Nutzereingaben abrufen

Nutzer der Filialsuche möchten in der Regel wissen, welches Geschäft in der Nähe ist oder an welcher Adresse sie beginnen möchten. Fügen Sie eine Place Autocomplete-Suchleiste hinzu, damit der Nutzer ganz einfach eine Startadresse eingeben kann. Die Place Autocomplete-Funktion ähnelt der Funktionsweise der automatischen Vervollständigung in anderen Google-Suchleisten. Die Vervollständigungen sind jedoch alle Orte in der Google Maps Platform.

  1. Gehen Sie zurück zu „index.html“, um Stile für die Suchleiste mit automatischer Vervollständigung und die zugehörige Seitenleiste 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 automatische Vervollständigung als auch der Schiebebereich sind anfangs ausgeblendet, bis sie benötigt werden.

  1. Jetzt kann das Autocomplete-Widget der Karte am Ende der Funktion initMap in app.js hinzugefügt werden, 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']);

Durch den Code werden die Vorschläge automatisch vervollständigt, sodass nur Adressen zurückgegeben werden, da Place Autocomplete für Namen von Einrichtungen und Verwaltungsstandorten abgeglichen werden kann. Außerdem werden die Adressen auf diejenigen im Vereinigten Königreich beschränkt. Wenn Sie diese optionalen Spezifikationen hinzufügen, reduziert sich die Anzahl der Zeichen, die der Nutzer eingeben muss, um die Vervollständigungen einzugrenzen, sodass die gewünschte Adresse angezeigt wird. Anschließend wird die von Google erstellte automatische Vervollständigung div oben rechts auf der Karte verschoben und angegeben, welche Felder zu jedem Ort in der Antwort zurückgegeben werden sollen.

  1. Starten Sie den Server neu und aktualisieren Sie die Vorschau, indem Sie den folgenden Befehl ausführen:
$ python3 -m http.server 8080

Jetzt sollte oben rechts auf der Karte das Autocomplete-Widget angezeigt werden.

5163f34a03910187

Jetzt müssen Sie verarbeiten, wenn der Nutzer eine Vorhersage aus dem Autocomplete-Widget auswählt und diesen Standort als Grundlage für die Berechnung der Entfernungen zu Ihren Geschäften verwendet.

  1. Fügen Sie folgenden Code am Ende von „initMap“ in „app.js“ 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. Wenn der Nutzer dann auf einen der Vorschläge klickt, wird die Karte auf die ausgewählte Adresse aktualisiert und der Ausgangspunkt als Grundlage für die Entfernungsberechnungen verwendet. Die Berechnung der Entfernung erfolgt im nächsten Schritt.

7. Geschäfte in der Nähe auflisten

Die Directions API funktioniert ähnlich wie das Anfordern von Wegbeschreibungen in der Google Maps App. Sie geben einen Abflugort und ein Ziel ein, um eine Route zwischen diesen Routen zu erhalten. Die Distance Matrix API nutzt dieses Konzept weiter, um die optimalen Kombinationen von mehreren möglichen Abflugorten und mehreren möglichen Zielen auf der Grundlage von Reisezeiten und Entfernungen zu erkennen. In diesem Fall helfen Sie dem Nutzer dabei, das nächstgelegene Geschäft für die ausgewählte Adresse zu finden. Geben Sie dazu einen Ursprung und ein Array von Geschäftsstandorten als Ziel an.

  1. Fügen Sie app.js eine neue Funktion mit dem Namen 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;
}

Durch die Funktion wird die Distance Matrix API mit dem ursprünglichen Ursprung als einzelne Quelle und den Geschäftsstandorten als Array von Zielen aufgerufen. Dann wird ein Array mit Objekten erstellt, in dem die ID des Geschäfts gespeichert wird, die Entfernung in einem menschenlesbaren String, die Entfernung in Metern als numerischer Wert und das Array sortiert.

Der Nutzer erwartet eine Liste der Geschäfte, die von der nächsten bis zur längsten Bestellung bestellt wurden. Über die Liste der von der Funktion calculateDistances zurückgegebenen Listen werden in der Seitenleiste die einzelnen Geschäfte aufgelistet.

  1. Fügen Sie app.js eine neue Funktion mit dem Namen 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, indem Sie den folgenden Befehl ausführen.
$ python3 -m http.server 8080
  1. Geben Sie dann eine Adresse im Vereinigten Königreich in die Suchleiste mit der automatischen Vervollständigung ein und klicken Sie auf einen der Vorschläge.

Die Karte sollte auf diese Adresse zentriert sein und in einer Seitenleiste sollten die Filialen in der Reihenfolge ihrer Entfernung zur ausgewählten Adresse aufgeführt sein. Hier ein Beispiel:

489628918395c3d0.png

8. Optional: Webseite hosten

Bis zu diesem Punkt können Sie eine Karte nur aufrufen, wenn Ihr Python-HTTP-Server aktiv ausgeführt wird. Wenn Sie Ihre Karte außerhalb einer aktiven Cloud Shell-Sitzung ansehen oder die URL mit anderen teilen möchten, sollten Sie Cloud Storage verwenden, um die Webseite zu hosten. Cloud Storage ist ein Onlinespeicherdienst, mit dem Daten in der Infrastruktur von Google gespeichert und abgerufen werden können. Dieser Dienst kombiniert die Leistung und Skalierbarkeit von Google Cloud mit erweiterten Sicherheits- und Freigabefunktionen. Es bietet außerdem eine kostenlose Stufe und ist ideal für die einfache Filialsuche.

Mit Cloud Storage werden Dateien in Buckets gespeichert, die den Verzeichnissen auf Ihrem Computer ähneln. Damit Sie Ihre Webseite hosten können, müssen Sie zuerst einen Bucket erstellen. Sie müssen einen eindeutigen Namen für den Bucket auswählen, z. B. als Teil des Bucket-Namens.

  1. Sobald Sie sich für einen Namen entschieden haben, führen Sie in Cloud Shell den folgenden Befehl 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 „Bucket erstellen“. Weitere Informationen zu allen verfügbaren Befehlen, einschließlich den verwendeten Befehlen, finden Sie unter gsutil-Tool.

Die in Cloud Storage gehosteten Buckets und Dateien sind standardmäßig privat. Für die Filialsuche sollten Sie jedoch festlegen, dass alle Dateien öffentlich zugänglich sind, damit jeder im Internet darauf zugreifen kann. Sie können jede Datei nach dem Hochladen veröffentlichen. Das ist aber sehr aufwendig. Stattdessen legen Sie einfach die Standardzugriffsebene für den erstellten Bucket fest und 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 den Bucket ausgewählt haben:
$ gsutil defacl ch -u AllUsers:R gs://yourname-store-locator
  1. Jetzt können Sie mit dem folgenden Befehl alle Dateien in das aktuelle 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, die Sie sehen möchten, lautet http://storage.googleapis.com/yourname-store-locator/index.html. Der Abschnitt „yourname-store-locator“ wird durch den zuvor ausgewählten Bucket-Namen ersetzt.

Clean-up

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

  • Öffne die Seite „Einstellungen“ in der Cloud Console
  • Klicken Sie auf Select a project (Projekt auswählen).
  • Wählen Sie das Projekt aus, das Sie am Anfang 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! Du hast dieses Codelab abgeschlossen.

Das haben Sie gelernt

Weitere Informationen

Welche weiteren Codelabs möchten Sie sehen?

Datenvisualisierung auf Google Maps Weitere Informationen zum Anpassen des Kartenstils Erstellen von 3D-Interaktionen in Karten

Ist das Codelab, das oben nicht aufgeführt werden soll? Hier können Sie ein neues Problem beantragen.

Weitere Informationen zum Code finden Sie im Quellcode-Repository unter https://github.com/googlecodelabs/google-maps-simple-store-locator.