Routenplaner mit Place Autocomplete und Routes API erstellen

1. Übersicht

Ob Sie einen Roadtrip planen, Ihren täglichen Arbeitsweg festlegen oder sich in einer geschäftigen Stadt zurechtfinden möchten – um von A nach B zu kommen, müssen Sie nicht nur wissen, wohin Sie möchten. Ein zuverlässiges Tool zur Routengenerierung ist unerlässlich.

Mit der Google Maps Platform können Sie Ihrer Anwendung eine dynamische Karte hinzufügen, Nutzern die schnelle Eingabe von Orten mit der Autovervollständigung ermöglichen und Routen auf der Karte anzeigen.

In diesem Codelab wird Entwicklern gezeigt, wie sie eine Webanwendung mit der Maps JavaScript API, Place Autocomplete und der Routes API erstellen. In einem anpassbaren Tutorial erfahren Sie, wie Sie mehrere Google Maps Platform APIs einbinden.

Aufgaben

In diesem Codelab erfahren Sie, wie Sie eine Webanwendung mit HTML, CSS, JavaScript und einem Node.js-Backend erstellen.

Architektur der Routenplaner-Web-App

Web-App für den Routenplaner

Lerninhalte

  • Google Maps Platform APIs aktivieren
  • Dynamische Karte in eine Webanwendung einbinden
  • „Place Autocomplete“-Dienst einbinden
  • Routen über die Routes API anfordern
  • Route auf einer dynamischen Karte anzeigen
  • Karten-ID erstellen
  • Erweiterte Markierungen in eine dynamische Karte einfügen

Voraussetzungen

Beispielcode

Die vollständige Lösung und der Schritt-für-Schritt-Code sind auf GitHub verfügbar. Der Code enthält nicht die erforderlichen Node-Pakete. Installieren Sie die erforderlichen Abhängigkeiten, bevor Sie den Code ausführen. Details zu den erforderlichen Paketen finden Sie in der Datei package.json(siehe Schritt 3).

2. Projekt einrichten und APIs aktivieren

Im Aktivierungsschritt müssen Sie die Maps JavaScript API, Place Autocomplete und die Routes API aktivieren.

Google Maps Platform einrichten

Wenn Sie noch kein Google Cloud-Konto und kein Projekt mit aktivierter Abrechnung haben, lesen Sie bitte den Leitfaden Erste Schritte mit Google Maps Platform, um ein Rechnungskonto und ein Projekt zu erstellen.

  1. Klicken Sie in der Cloud Console auf das Drop-down-Menü für das Projekt und wählen Sie das Projekt aus, das Sie für dieses Codelab verwenden möchten. Projekt auswählen
  2. Aktivieren Sie die für dieses Codelab erforderlichen Google Maps Platform APIs auf der Seite Maps API Library. Folgen Sie dazu der Anleitung in diesem Video oder dieser Dokumentation.
  3. Generieren Sie einen API-Schlüssel in der Cloud Console auf der Seite Anmeldedaten. In diesem Video und in dieser Dokumentation finden Sie eine Anleitung. Für alle Anfragen an die Google Maps Platform ist ein API-Schlüssel erforderlich.

3. Node.js-Projekt einrichten

In diesem Lab verwenden wir Node.js, um den Start- und Zielort aus dem Web abzurufen und die Route über die Routes API anzufordern.

Wenn Sie Node.js bereits installiert haben, erstellen Sie ein Verzeichnis, in dem Sie dieses Projekt ausführen:

$ mkdir ac_routes
$ cd ac_routes

Initialisieren Sie ein neues Node.js-Paket im Verzeichnis für Ihre Anwendung:

$ npm init

Mit diesem Befehl werden Sie aufgefordert, verschiedene Informationen anzugeben, z. B. den Namen und die Version Ihrer Anwendung. Drücken Sie vorerst einfach die EINGABETASTE, um die Standardeinstellungen für die meisten zu übernehmen. Der Standardeinstiegspunkt ist „index.js“. Sie können ihn in Ihre Hauptdatei ändern. In diesem Lab ist die Hauptdatei „function/server.js“ (weitere Informationen in Schritt 6).

Außerdem können Sie Ihr bevorzugtes Framework und Ihre bevorzugten Module installieren. In diesem Lab werden das Web-Framework Express und der Body-Parser body-parser verwendet. Weitere Informationen finden Sie in der Datei package.json.

4. Dynamische Karte erstellen

Nachdem wir das Node.js-Backend eingerichtet haben, sehen wir uns nun die erforderlichen Schritte für die Clientseite an.

  • HTML-Seite für die Anwendung erstellen
  • CSS-Datei zum Festlegen des Stils erstellen
  • Google Maps JavaScript API in die HTML-Seite laden
  • Fügen Sie Ihren API-Schlüssel in das Script-Tag ein, um Ihre Anwendung zu authentifizieren.
  • JavaScript-Datei zum Verarbeiten der Anwendungsfunktionen erstellen

HTML-Seite erstellen

  1. Erstellen Sie in Ihrem Projektordner(in diesem Fall „ac_routes“) ein neues Verzeichnis.
     $ mkdir public
     $ cd public
    
  2. Erstellen Sie im öffentlichen Verzeichnis die Datei „index.html“.
  3. Kopieren Sie den folgenden Code in die Datei „index.html“:
     <!DOCTYPE html>
     <html>
     <head>
       <title>GMP Autocomplete + Routes</title>
       <meta charset="utf-8">
       <link rel="stylesheet" type="text/css" href="style.css">
     </head>
     <body>
       <div class="container">
         <!-- Start of the container for map -->
         <div class="main">
           <div id="map"></div>
         </div>
         <!-- End of the container for map -->
       </div>
       </body>
     </html>
    

CSS-Datei erstellen

  1. Erstellen Sie die Datei „style.css“ im öffentlichen Verzeichnis.
  2. Kopieren Sie den folgenden Code in style.css:
     html, body {height: 100%;}
     body {
       background: #fff;
       font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
       font-style: normal;
       font-weight: normal;
       font-size:16px;
       line-height: 1.5;
       margin: 0;
       padding: 0;
     }
     .container {display:flex; width:90%; padding:100px 0; margin:0 auto;}
     .main {width:70%; height:800px;}
      #map {height:100%; border-radius:20px;}
    

Maps JavaScript API laden

In diesem Lab verwenden wir den dynamischen Bibliotheksimport, um die Maps JavaScript API zu laden. Weitere Informationen findest du hier.

Kopieren Sie in der Datei „index.html“ den folgenden Code vor dem schließenden body-Tag. Ersetzen Sie „YOUR_API_KEY“ durch Ihren eigenen API-Schlüssel.

<script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({key: "YOUR_API_KEY", v: "weekly"});</script>

JavaScript-Datei erstellen

  1. Erstellen Sie im öffentlichen Verzeichnis die Datei „app.js“.
  2. Kopieren Sie den folgenden Code in „app.js“:
     (function(){
       let map;
    
       async function initMap() {
           const { Map } = await google.maps.importLibrary('maps');
           map = new Map(document.getElementById('map'), {
               center: { lat: -34.397, lng: 150.644 },
               zoom: 8,
               mapId: 'DEMO_MAP_ID'
           });
       }
    
       initMap();
     }());
    

Die DEMO_MAP_ID ist eine ID, die für Codebeispiele verwendet werden kann, für die eine Karten-ID erforderlich ist. Diese ID ist nicht für die Verwendung in Produktionsanwendungen vorgesehen und kann nicht für Funktionen verwendet werden, für die Cloud-Styling erforderlich ist. In diesem Lab benötigen wir später eine Karten-ID für erweiterte Markierungen. Weitere Informationen zum Erstellen einer Karten-ID für Ihre Anwendung

Verknüpfen Sie in der Datei „index.html“ die Datei „app.js“ vor dem schließenden „body“-Tag und nach dem Script-Tag zum Laden der Maps JavaScript API.

<script type="text/JavaScript" src="app.js"></script>

Vollständiger Beispielcode

Der vollständige Code bis zu diesem Punkt ist auf GitHub:step1_createDynamicMap verfügbar.

5. Adressen für Start- und Zielort eingeben

  • Fügen Sie in der Datei „index.html“ zwei Textfelder für die Eingabe von Start und Ziel hinzu.
  • Bibliothek für die automatische Vervollständigung importieren
  • Autocomplete-Dienst an die Textfelder für Start- und Zielort binden

Textfelder hinzufügen

Fügen Sie in der Datei „index.html“ den folgenden Code als erstes untergeordnetes Element von div mit der Klasse container hinzu.

<div class="aside">
  <div class="inputgroup">
    <label for="origin">Start</label>
    <input type="text" id="origin" name="origin" class="input-location" placeholder="Enter an address">
  </div>
  <div class="inputgroup">
    <label for="origin">End</label>
    <input type="text" id="destination" name="destination" class="input-location" placeholder="Enter an address">
  </div>
</div>

Automatische Vervollständigung importieren und aktivieren

Die Klasse google.maps.places.Autocomplete ist ein Widget, das Ortsvorhersagen basierend auf der Texteingabe eines Nutzers bereitstellt. Es wird an ein Eingabeelement vom Typ „text“ angehängt und überwacht die Texteingabe in diesem Feld. Die Liste der Vorschläge wird als Drop-down-Liste angezeigt und aktualisiert, sobald Text eingegeben wird.

Fügen Sie in app.js nach der Karteninitialisierung den folgenden Code ein:

let placeIds = [];
async function initPlace() {
  const { Autocomplete } = await google.maps.importLibrary('places');
  let autocomplete = [];
  let locationFields = Array.from(document.getElementsByClassName('input-location'));
  //Enable autocomplete for input fields
  locationFields.forEach((elem,i) => {
      autocomplete[i] = new Autocomplete(elem);
      google.maps.event.addListener(autocomplete[i],"place_changed", () => {
          let place = autocomplete[i].getPlace();
          if(Object.keys(place).length > 0){
              if (place.place_id){
                  placeIds[i] = place.place_id; //We use Place Id in this example
              } else {
                  placeIds.splice(i,1); //If no place is selected or no place is found, remove the previous value from the placeIds.
                  window.alert(`No details available for input: ${place.name}`);
                  return;
              }
          }
      });
  });
}
initPlace();

Sobald ein Nutzer einen Ort aus der Liste mit Autocomplete-Vorschlägen auswählt, können Sie mit der Methode getPlace() ein Place-Ergebnisdetail abrufen. Das Orts-Ergebnis enthält viele Informationen zu einem Ort. In diesem Lab verwenden wir place_id, um den ausgewählten Ort zu identifizieren. Mit einer Orts-ID wird ein Ort in der Google Places-Datenbank und in Google Maps eindeutig identifiziert. Weitere Informationen zu Orts-IDs

Relevante Stile hinzufügen

Fügen Sie in style.css den folgenden Code hinzu:

.aside {width:30%; padding:20px;}
.inputgroup {margin-bottom:30px;}
.aside label {display:block; padding:0 10px; margin-bottom:10px; font-size:18px; color:#666565;}
.aside input[type=text] {width:90%;padding:10px; font-size:16px; border:1px solid #e6e8e6; border-radius:10px;}

Vollständiger Beispielcode

Der vollständige Code bis zu diesem Punkt ist auf GitHub:step2_inputAddress verfügbar.

6. Route anfordern

  • Schaltfläche „Route abrufen“ zu index.html hinzufügen, um die Routenanfrage zu starten
  • Mit dieser Schaltfläche werden Ursprungs- und Zieldaten an den Node.js-Dienst gesendet.
  • Der Node.js-Dienst sendet eine Anfrage an die Routes API.
  • Die API-Antwort wird zur Anzeige an die Clientseite zurückgegeben.

Nachdem Sie Start- und Zielort festgelegt und eine dynamische Karte erstellt haben, können Sie die Route abrufen. Die Routes API, die nächste Generation der leistungsoptimierten Version des Directions- und Distance Matrix-Dienstes, kann hier Abhilfe schaffen. In diesem Lab verwenden wir Node.js, um den Start- und Zielort aus dem Web abzurufen und die Route über die Routes API anzufordern.

Fügen Sie in der Datei „index.html“ vor dem schließenden Tag von div mit der Klasse aside die Schaltfläche „Route abrufen“ ein :

<div class="inputgroup">
  <button id="btn-getroute">Get a route</button>
</div>

Fügen Sie in style.css die folgende Zeile hinzu:

.aside button {padding:20px 30px; font-size:16px; border:none; border-radius:50px; background-color:#1a73e8; color:#fff;}

Fügen Sie in „app.js“ den folgenden Code ein, um Start- und Zielortdaten an den Node.js-Dienst zu senden:

function requestRoute(){
  let btn = document.getElementById('btn-getroute');
  btn.addEventListener('click', () => {
    //In this example, we will extract the Place IDs from the Autocomplete response
    //and use the Place ID for origin and destination
    if(placeIds.length == 2){
        let reqBody = {
            "origin": {
                "placeId": placeIds[0]
            },
            "destination": {
                "placeId": placeIds[1]
            }
        }

        fetch("/request-route", {
            method: 'POST',
            body: JSON.stringify(reqBody),
            headers: {
                "Content-Type": "application/json"
            }
        }).then((response) => {
            return response.json();
        }).then((data) => {
            //Draw the route on the map
            //Details will be covered in next step
            renderRoutes(data);
        }).catch((error) => {
            console.log(error);
        });
    } else {
        window.alert('Location must be set');
        return;
    }
  });
}

requestRoute();

renderRoutes() ist die Funktion, mit der wir die Route auf der Karte zeichnen. Die Details werden im nächsten Schritt erläutert.

Server erstellen

Erstellen Sie im Projektverzeichnis(in diesem Fall „ac_routes“) einen neuen Ordner mit dem Namen „function“. Erstellen Sie in diesem Ordner eine Datei mit dem Namen „server.js“. Die Datei dient als Einstiegspunkt Ihres Projekts, der beim Einrichten Ihres Node.js-Projekts konfiguriert wird. Sie übernimmt drei wichtige Funktionen:

  1. Daten vom Webclient erheben
  2. Anfragen an die Routes API senden
  3. API-Antwort an die Clientseite zurückgeben

Kopieren Sie den folgenden Code in die Datei „server.js“. Ersetzen Sie „YOUR_API_KEY“ durch Ihren eigenen API-Schlüssel. Um die Sicherheit von API-Schlüsseln zu erhöhen, empfehlen wir dringend, einen separaten Schlüssel für das Backend zu verwenden. Weitere Informationen finden Sie unter Sicherheitshinweise.

const express = require('express');
const app = express();
const bodyParser = require('body-parser');

const port  = 8080;
const urlencodedParser = bodyParser.urlencoded({extended:true}); 

function main() {
  app.use('/', express.static('public'));
  app.use(urlencodedParser);
  app.use(express.json());

  app.post('/request-route', (req,res) => {    
    fetch("https://routes.googleapis.com/directions/v2:computeRoutes", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Goog-Api-Key": "YOUR_API_KEY",
        "X-Goog-FieldMask": "*"
      },
      body: JSON.stringify(req.body)
    }).then((response) => {
      return response.json();
    }).then((data) => {
      if('error' in data){
        console.log(data.error);
      } else if(!data.hasOwnProperty("routes")){
        console.log("No route round");
      } else {
        res.end(JSON.stringify(data));
      }
    }).catch((error) => {
      console.log(error)
    });
  });

  app.listen(port, () => {
      console.log('App listening on port ${port}: ' + port);
      console.log('Press Ctrl+C to quit.');
  });
}

main();

Weitere Informationen zur Routes API

Code ausführen

Führen Sie den folgenden Code in der Befehlszeile aus:

$ node function/server.js

Öffnen Sie den Browser und rufen Sie http://127.0.0.1:8080/index.html auf. Sie sollten die Anwendungsseite sehen. Bis zu diesem Punkt wird die API-Antwort an den Webclient zurückgegeben. Im nächsten Schritt sehen wir uns an, wie die Route auf der Karte angezeigt wird.

Vollständiger Beispielcode

Der vollständige Code bis zu diesem Punkt ist auf GitHub:step3_requestRoute verfügbar.

7. Route auf der Karte anzeigen

Im vorherigen Schritt haben wir uns auf renderRoutes() bezogen, wenn wir die Antwort vom Node.js-Dienst erfolgreich erhalten haben. Jetzt fügen wir den eigentlichen Code hinzu, um die Route auf der Karte darzustellen.

Fügen Sie in app.js den folgenden Code hinzu:

let paths = [];
async function renderRoutes(data) {
  const { encoding } = await google.maps.importLibrary("geometry");
  let routes = data.routes;
  let decodedPaths = [];

  ///Display routes and markers
  routes.forEach((route,i) => {
      if(route.hasOwnProperty('polyline')){
        //Decode the encoded polyline
        decodedPaths.push(encoding.decodePath(route.polyline.encodedPolyline));

        //Draw polyline on the map
        for(let i = decodedPaths.length - 1; i >= 0; i--){
            let polyline = new google.maps.Polyline({
                map: map,
                path: decodedPaths[i],
                strokeColor: "#4285f4",
                strokeOpacity: 1,
                strokeWeight: 5
            });
            paths.push(polyline);
        }
        
        //Add markers for origin/destination
        addMarker(route.legs[0].startLocation.latLng,"A");
        addMarker(route.legs[0].endLocation.latLng,"B");
        //Set the viewport
        setViewport(route.viewport);
      } else {
        console.log("Route cannot be found");
      }
  });
}

Die Routes API gibt Polylinien entweder im Format „encodedPolyline“ (Standard) oder „geoJsonLinestring“ zurück. In diesem Lab verwenden wir das Format „encodedPolyline“ und decodieren es mit der Maps JavaScript-Geometrie-Bibliothek.

Wir verwenden addMarker(), um erweiterte Markierungen für Start und Ziel hinzuzufügen. Fügen Sie in app.js den folgenden Code hinzu:

let markers = [];
async function addMarker(pos,label){
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
  const { PinElement } = await google.maps.importLibrary("marker");
  const { LatLng } = await google.maps.importLibrary("core");
  let pinGlyph = new PinElement({
      glyphColor: "#fff",
      glyph: label
  });
  let marker = new AdvancedMarkerElement({
      position: new LatLng({lat:pos.latitude,lng:pos.longitude}),
      gmpDraggable: false,
      content: pinGlyph.element,
      map: map
  });
  markers.push(marker);
}

Hier erstellen wir zwei erweiterte Markierungen: A für den Ursprung und B für das Ziel. Weitere Informationen zu erweiterten Markierungen

Als Nächstes zentrieren wir den Karten-Viewport auf der abgerufenen Route. Dazu verwenden wir die praktischen viewport-Informationen, die von der Routes API bereitgestellt werden. Fügen Sie in app.js den folgenden Code hinzu:

async function setViewport(viewPort) {
  const { LatLng } = await google.maps.importLibrary("core");
  const { LatLngBounds } = await google.maps.importLibrary("core");
  let sw = new LatLng({lat:viewPort.low.latitude,lng:viewPort.low.longitude});
  let ne = new LatLng({lat:viewPort.high.latitude,lng:viewPort.high.longitude});
  map.fitBounds(new LatLngBounds(sw,ne));
}

Vollständiger Beispielcode Der vollständige Code bis zu diesem Punkt ist auf GitHub:step4_displayRoute verfügbar.

8. Elemente aus der Karte entfernen

Hier möchten wir einen Schritt weitergehen. Wir löschen die Karte, bevor wir neue Markierungen und Routen einzeichnen, um Unübersichtlichkeit zu vermeiden.

Fügen wir in app.js eine weitere Funktion hinzu:

function clearUIElem(obj,type) {
  if(obj.length > 0){
      if(type == 'advMarker'){
          obj.forEach(function(item){
              item.map = null;
          });
      } else {
          obj.forEach(function(item){
              item.setMap(null);
          });
      }
  }
}

Fügen Sie am Anfang von renderRoutes() die folgende Zeile hinzu:

clearUIElem(paths,'polyline');

Fügen Sie am Anfang von addMarker() die folgende Zeile hinzu:

clearUIElem(markers,'advMarker');

Vollständiger Beispielcode

Der vollständige Code bis zu diesem Punkt ist auf GitHub:step5_removeElements verfügbar.

9. Glückwunsch

Sie haben das Gerät erfolgreich gebaut.

Das haben Sie gelernt

  • Google Maps Platform APIs aktivieren
  • Google Maps JavaScript API in die HTML-Seite laden
  • Places Library, Maps JavaScript API importieren
  • „Place Autocomplete“-Dienst an die Textfelder binden
  • Route über die Routes API anfordern
  • Route auf einer dynamischen Karte anzeigen
  • Karten-ID erstellen
  • Erweiterte Markierungen erstellen

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.