Zum Inhalt

Routing

Mit dieser Klasse können Sie Routenberechnungen durchführen.

Anweisungen

Für die Implementierung eines Formulars, das die Routenberechnung mit Geocoding auf der SmartMaps-Karte ermöglicht, wird zunächst ein div-Element mit der ID map-wrapper zum Body-Tag des HTML-Skripts hinzugefügt.

<div id="map-wrapper">
  ...
</div>

Der map-wrapper enthält ein weiteres div-Element mit der Klasse geocoder-form. In diesem Element wird die Benutzeroberfläche für die Eingabe der Adressinformationen von Start- und Endpunkt implementiert. Beispielsweise kann das Geocoding von Start- und Endpunkt in einem Formular (ID=route-single-slot-form) durch jeweils ein Eingabefeld realisiert werden. Die vom Nutzer eingegebenen Daten werden dynamisch verarbeitet, und es wird automatisch erkannt, um welche Adressinformationen es sich handelt. Das Eingabefeld des Startpunkts erhält die ID RouteStart und das Eingabefeld des Endpunkts die ID RouteEnd.

<div class="geocoder-form" style="z-index:1000">
  <form id="route-single-slot-form">
    <fieldset>
      <input type="text" name="RouteStart" id="RouteStart" value="76131" placeholder="RouteStart">
      <input type="text" name="RouteEnd" id="RouteEnd" value="76228" placeholder="RouteEnd">
      <button type="submit">send</button>
    </fieldset>
  </form>
</div>

Um die SmartMaps-Karte anzuzeigen, enthält der map-wrapper ein leeres div-Element mit der ID map. In dieses div-Element wird die Karte zur Laufzeit geladen. Für das div-Element können Sie mit dem Attribut style eine feste Höhe und Breite für die Karte festlegen.

<div id="map" style="height: 400px; width: 500px;"></div>

Um Routing und Geocoding auf der Benutzeroberfläche zu ermöglichen, muss JavaScript-Code eingebunden werden. Wie in diesem Beispiel kann dieser Code entweder im HTML-Skript oder in einer separaten .js-Datei über ein Script-Tag eingebunden werden. Alle Variablen und Funktionen werden in der Methode ym.ready implementiert, da diese Methode Abhängigkeiten auflöst, um die eigentliche Kartenanwendung zu starten.

Um Zugriff auf die Nutzereingabe zu haben, wird das Adressformular route-single-slot-form zunächst in der Variable routeSingleSlotForm gespeichert. Für die Routenberechnung der geocodierten Adresse wird ein Objekt der Klasse ym.services.Routing() erstellt und in der Variable routing gespeichert.

ym.ready(function(modules) {
  var routeSingleSlotForm = document.getElementById('route-single-slot-form');
  var routing = new ym.services.Routing();

Der Karteninhalt wird durch die Variable stationLayer gesteuert, bei der es sich um ein Objekt der Klasse ym.layerGroup handelt. Diese repräsentiert eine Layer-Gruppe, mit der die SmartMaps-Karte und ihre Objekte layerweise verwaltet werden. Außerdem wird eine Array-Variable waypoints initialisiert, die mit den Wegpunkten einer Route gefüllt wird.

  // Define map content.
  var stationLayer = ym.layerGroup();
  var waypoints = [];

Zusätzlich wird ein Route-Layer benötigt, der die vollständige Logik zum Zeichnen der Route auf der Karte enthält. Dabei handelt es sich um ein GeoJSON-Objekt, in dem die Polylinie und das Erscheinungsbild für die Wegpunkte der Route definiert werden.

  // Set route layer. This is the complete logic to create a route with all 
  // their stations to draw.
  routingLayer = ym.geoJson(null, {
    style: function(feature) {
      // Drawing a polyline
      if (feature.geometry.type === "LineString") {
        return {
          weight: 7,
          opacity: 0.8
        };
      }
    },
    pointToLayer: function(feature, latlng) {
      // Draw in stations with information.
      var waypointMarker = ym.circleMarker(latlng);
      waypointMarker.bindPopup(feature.properties.description);
      return waypointMarker;
    }
  });

Um die SmartMaps-Karte anzuzeigen, wird ein Objekt der Klasse ym.map erstellt. Die ID des div-Elements, in dem die Karte gezeichnet werden soll, sowie die gewünschten Kartenoptionen (Startposition, Start-Zoomstufe usw.) werden als Parameter übergeben. Um die Karte im Code weiter verwalten zu können, wird das Objekt in einer Variable map gespeichert. Anschließend werden die zuvor erstellte Layer-Gruppe und der definierte Route-Layer zur Karte hinzugefügt.

  // Define map.
  var map = ym.map("map", {
    center: ym.latLng(48.991897, 8.435568),
    zoom: 13
  });
  // Draw in route layer.
  map.addLayer(routingLayer);
  map.addLayer(stationLayer);

Im nächsten Schritt werden die vom Nutzer eingegebenen Adressdaten geocodiert. Für den Status onsubmit der Variable routeSingleSlotForm wird eine Funktionsfolge definiert. Wenn das Formular vom Nutzer abgeschickt wird, werden zunächst alle Inhalte der Karte geleert. Anschließend werden die Eingabefelder des Formulars ausgelesen, um die darin enthaltenen Adressdaten zu geocodieren.

  routeSingleSlotForm.onsubmit = function(e) {
    // Discard old card content.
    waypoints = [];
    if (routingLayer) {
      routingLayer.clearLayers();
    }
    if (stationLayer) {
      stationLayer.clearLayers();
    }
    e.preventDefault();
    modules.geocodeString(document.getElementById('RouteStart').value);
    modules.geocodeString(document.getElementById('RouteEnd').value);
  };

Um das Geocoding zu verfolgen, wird für die Klasse geoCoder, die das Geocoding auf der SmartMaps-Karte ermöglicht, ein EventEmitter verwendet. Dieser ermöglicht es über seine on-Methode, einen Listener hinzuzufügen. Der Listener führt bei bestimmten Ereignissen Funktionen aus und kann verwendet werden, um zwischen erfolgreichem und nicht erfolgreichem Geocoding zu unterscheiden. In diesem Fall ist die Klasse geoCoder bereits mit einem EventEmitter ausgestattet und kann direkt auf die on-Methode zugreifen.

Bei erfolgreichem Geocoding ('success') wird an der geocodierten Adresse ein Marker auf der Karte gesetzt, der beim Anklicken ein Pop-up-Fenster mit den Adressdaten anzeigt. Der Marker wird als Layer in die SmartMaps-Karte eingefügt. Abschließend wird die geocodierte Adresse im Array waypoints für die Routenberechnung gespeichert. Sobald mehr als ein Eintrag im Array vorhanden ist, wird die Methode calcRoute() mit dem Array waypoints als Parameter für die Routenberechnung aufgerufen. Die Methode calcRoute() ist in der Klasse ym.services.Routing() definiert, die als Objekt in der Variable routing gespeichert wurde.

  ym.services.geoCoder.on('success', function(req, res) {
    var geoJSONCoords = [];
    var geoJson = ym.geoJson(res.body, {
      onEachFeature: function(feature, layer) {
        layer.setIcon(ym.provider.Icon.Default());
        var popUpContent = "";
        if (feature.properties.street) {
          popUpContent += feature.properties.street + ", ";
        }
        if (feature.properties.zip) {
          popUpContent += feature.properties.zip + " ";
        }
        if (feature.properties.city) {
          popUpContent += feature.properties.city + " ";
        }
        if (feature.properties.cityPart) {
          popUpContent += feature.properties.cityPart;
        }
        layer.bindPopup(popUpContent);
        geoJSONCoords.push(ym.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates));
      }
    });
    stationLayer.addLayer(geoJson);

    // If there is more than one result in the list with the geocoded addresses, 
    // it will use the first one.
    waypoints.push(geoJSONCoords);

    if (waypoints.length > 1) {
      routing.calcRoute(waypoints);
    }
  });

Die Klasse ym.services.Routing() verfügt ebenfalls über die on-Methode der EventEmitter-Klasse, um die Route bei erfolgreicher Routenberechnung ('success') auf der Karte zu zeichnen.

  routing.on("success", function(request, response) {
    routingLayer.addData(response.body);
    map.fitBounds(routingLayer.getBounds());
  });

Bei nicht erfolgreichem Geocoding ('error') wird ein Eintrag in die Konsole geschrieben, und es wird keine Routenberechnung durchgeführt.

  ym.services.geoCoder.on('error', function(req, res, errorType) {
    console.log(arguments);
  });

Die Routenberechnung ist nun erfolgreich integriert.

HTML-Dokument

Codebeispiel: Routing

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title>Routing</title>
</head>
<body>
  <div id="map-wrapper">
    <div class="geocoder-form" style="z-index:1000">
      <form id="route-single-slot-form">
        <fieldset>
          <input type="text" name="RouteStart" id="RouteStart" value="76131" placeholder="RouteStart">
          <input type="text" name="RouteEnd" id="RouteEnd" value="76228" placeholder="RouteEnd">
          <button type="submit">send</button>
        </fieldset>
      </form>
    </div>
    <div id="map" style="width: 600px; height: 600px;"></div>
  </div>
  <!-- SmartMaps-API -->
  <script
    src="https://www.yellowmap.de/api_rst/api/loader?libraries=free-3&apiKey=[INSERT API-KEY]"></script>
  <script>
    ym.ready(function (modules) {
      var routeSingleSlotForm = document.getElementById('route-single-slot-form');
      var routing = new ym.services.Routing();

      // Define map content.
      var stationLayer = ym.layerGroup();
      var waypoints = [];
      // Set route layer. This is the complete logic to create a route with all 
      // their stations to draw.
      routingLayer = ym.geoJson(null, {
        style: function (feature) {
          // Drawing a polyline
          if (feature.geometry.type === "LineString") {
            return {
              weight: 7,
              opacity: 0.8
            };
          }
        },
        pointToLayer: function (feature, latlng) {
          // Draw stations with information.
          var waypointMarker = ym.circleMarker(latlng);
          waypointMarker.bindPopup(feature.properties.description);
          return waypointMarker;
        }
      });
      // Define map
      var map = ym.map("map", {
        center: ym.latLng(48.991897, 8.435568),
        zoom: 13
      });
      // Draw in route layer.
      map.addLayer(routingLayer);
      map.addLayer(stationLayer);

      routeSingleSlotForm.onsubmit = function (e) {
        // Discard old map content.
        waypoints = [];
        if (routingLayer) {
          routingLayer.clearLayers();
        }
        if (stationLayer) {
          stationLayer.clearLayers();
        }
        e.preventDefault();
        modules.geocodeString(document.getElementById('RouteStart').value);
        modules.geocodeString(document.getElementById('RouteEnd').value);
      }
      ym.services.geoCoder.on('success', function (req, res) {
        var geoJSONCoords = [];
        var geoJson = ym.geoJson(res.body, {
          onEachFeature: function (feature, layer) {
            layer.setIcon(ym.provider.Icon.Default());
            var popUpContent = "";
            if (feature.properties.street) {
              popUpContent += feature.properties.street + ", ";
            }
            if (feature.properties.zip) {
              popUpContent += feature.properties.zip + " ";
            }
            if (feature.properties.city) {
              popUpContent += feature.properties.city + " ";
            }
            if (feature.properties.cityPart) {
              popUpContent += feature.properties.cityPart;
            }
            layer.bindPopup(popUpContent);
            geoJSONCoords.push(ym.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates));
          }
        });
        stationLayer.addLayer(geoJson);
        // If there is more than one result in the list with the geocoded addresses, 
        // it will use the first one.
        waypoints.push(geoJSONCoords);
        if (waypoints.length > 1) {
          routing.calcRoute(waypoints);
        }
      });
      routing.on("success", function (request, response) {
        routingLayer.addData(response.body);
        map.fitBounds(routingLayer.getBounds());
      });
      ym.services.geoCoder.on('error', function (req, res, errorType) {
        console.log(arguments);
      });
    });
  </script>
</body>
</html>