Routing
You can use this class to perform route calculations.
Instructions
For the implementation of a form that enables route calculation with geocoding on the SmartMaps map, a div
element with the ID map-wrapper
is first added to the body
tag of the HTML script.
<div id="map-wrapper"> ... </div>.
The map-wrapper
contains another div
element with the class geocoder-form
. In this element the user interface for the input of the address information of the start and end point is implemented. For example, the geocoding of the start and end point in a form (ID=route-single-slot-form
) can be realized by one input field each. The data entered by the user is processed dynamically and it is automatically recognized which address information is involved.
The input field of the start point gets the ID RouteStart
and the input field of the end point gets the 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>
To display the SmartMaps map, the map-wrapper
contains an empty div
element with the ID map
. In this div-element the map is loaded at runtime. For the div-element you can set a fixed height and width for the map with the style
-attribute.
To enable routing and geocoding on the user interface, JavaScript code must be included. As in this example, this code can be included in the HTML script
or in a separate .js file using a script tag. All variables and functions are implemented in the ym.ready
method, because this method resolves dependencies to start the actual map application.
In order to have access to the user input, the address form route-single-slot-form
is stored in the variable routeSingleSlotForm
for the time being. For the route calculation of the geocoded address an object of the class ym.services.Routing()
is created and stored in the variable routing
.
ym.ready(function(modules) {
var routeSingleSlotForm = document.getElementById('route-single-slot-form');
var routing = new ym.services.Routing();
The map content is controlled by the variable stationLayer
, which is an object of the class ym.layerGroup
. This represents a layer group, which is used to manage the SmartMaps map and its objects by layers. Also an array variable waypoints is initialized, which is filled with the waypoints
of a route.
// Define map content.
var stationLayer = ym.layerGroup();
var waypoints = [];
Additionally a route layer is needed, which contains the complete logic for drawing the route on the map. This is a GeoJSON
object in which the polyline and appearance for the waypoints of the route are defined.
// 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;
}
});
To display the SmartMaps map, an object of the class ym.map
is created. The ID of the div
element in which the map is to be drawn and the desired map options (start position, start zoom level, etc.) are passed as parameters. To continue managing the map in code, the object is stored in a variable map
. The previously created layer group and the defined route layer will be added to the map afterwards.
// 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);
In the next step, the address data entered by the user is geocoded. A function sequence is defined for the status onsubmit
of the variable routeSingleSlotForm
. When the form is sent by the user, all contents of the map are emptied. Afterwards the input fields of the form are read out to geocode the adress data, which are contained as values.
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);
};
To track the geocoding, an EventEmitter
is used for the geoCoder
class, which enables geocoding on the SmartMaps map. This enables by its on
-method that a listener is added. The listener performs functions on certain events and can be used to distinguish between successful and unsuccessful geocoding. In this case the geoCoder
class is already equipped with an EventEmitter
and can directly access the on
-method.
In case of a successful geo-coding ('success'
) a marker is set at the geo-coded address on the map, which shows a popup window with the address data when clicked. The marker is inserted as a layer in the SmartMaps map. Finally the geocoded address is stored in the waypoints
array for route calculation. As soon as there is more than one entry in the array, the calcRoute()
method is called with the waypoints
array as parameter for the route calculation. The calcRoute()
method is defined in the ym.services.Routing()
class, which has been stored as an object in the variable routing
.
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[0]));
}
});
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[0]);
if (waypoints.length > 1) {
routing.calcRoute(waypoints);
}
});
The ym.services.Routing()
class also has the on method of the EventEmitter
class to draw the route on the map in case of a successful route calculation ('success'
).
routing.on("success", function(request, response) {
routingLayer.addData(response.body);
map.fitBounds(routingLayer.getBounds());
});
In case of an unsuccessful geocoding ('error'
) an entry is written to the console and no route calculation is performed.
ym.services.geoCoder.on('error', function(req, res, errorType) {
console.log(arguments);
});
The route calculation is now successfully integrated.
HTML document
Code example: 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={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) {
// Stationen mit Informationen einzeichnen.
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 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);
}
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[0]));
}
});
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[0]);
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>