Here [a jsFiddle demo][1], which draws OSRM route service response by geometry:
[![OpenStreetMap with OSRM routes and markers][2]][2]
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
'use strict';
function processOsrmReply(data) {
console.log('Received OSRM map matching reply:');
console.log(data);
myMap.flyToBounds(markersGroup.getBounds());
if (data.code !== 'Ok') {
clearMap('Error code: ' + data.code);
return;
}
data.routes.forEach(function(route) {
routesGroup.addData(route.geometry);
});
}
function sendOsrmRequest() {
var url = 'https://router.project-osrm.org/route/v1/car/' +
parseFloat(startMarker.getLatLng().lng).toFixed(6) + ',' +
parseFloat(startMarker.getLatLng().lat).toFixed(6) + ';' +
parseFloat(finalMarker.getLatLng().lng).toFixed(6) + ',' +
parseFloat(finalMarker.getLatLng().lat).toFixed(6) +
'?overview=simplified' +
'&alternatives=3' +
'&steps=false' +
'&annotations=false' +
'&geometries=geojson';
console.log('Sending OSRM route query to the URL ' + url);
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.response);
processOsrmReply(data);
} else {
clearMap('Error status: ' + this.status);
}
};
request.send();
}
function clearMap(str = '') {
var myStatus = document.getElementById('myStatus');
myStatus.textContent = str;
linesGroup.clearLayers();
}
var startPosition = [55.75044, 37.61749];
var finalPosition = [47.22165, 39.70960];
var myMap = L.map('myMap').setView(startPosition, 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(myMap);
var markersGroup = L.featureGroup();
myMap.addLayer(markersGroup);
var routesGroup = L.geoJSON();
myMap.addLayer(routesGroup);
var overlays = {
'Show start and finish markers': markersGroup,
'Show OSRM route geometry': routesGroup
};
L.control.layers(null, overlays, {
collapsed: false
}).addTo(myMap);
var startMarker = L.marker(startPosition, {
draggable: true,
title: 'start'
})
.on('dragend', sendOsrmRequest)
.addTo(markersGroup);
var finalMarker = L.marker(finalPosition, {
draggable: true,
title: 'finish'
})
.on('dragend', sendOsrmRequest)
.addTo(markersGroup);
sendOsrmRequest();
<!-- language: lang-css -->
html, body {
margin: 0;
padding: 0;
}
#myMap {
position: absolute;
width: 100%;
height: 100%;
}
<!-- language: lang-html -->
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet.min.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet-src.min.js"></script>
<div id="myMap"></div>
<!-- end snippet -->
[1]: https://jsfiddle.net/afarber/5ceqdtkr/
[2]: https://i.stack.imgur.com/tIGrS.gif
To retrieve the map matched node coordinates, you could accompany the OSRM query by Overpass API queries - one per each leg - as in [the jsFiddle demo][1]:
[![animated map][2]][2]
After the nodes are parsed from Overpass API calls, you could match their coordinates against the `matching.geometry.coordinates` in the Javascript code:
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
'use strict';
function processOsrmReply(data) {
console.log('Received OSRM map matching reply:');
console.log(data);
if (data.code !== 'Ok') {
clearMap('OSRM error code: ' + data.code);
return;
}
for (var m = 0; m < data.matchings.length; m++) {
var matching = data.matchings[m];
var coordinates = matching.geometry.coordinates;
// alternate line colors to see the different matchings
var lineColor = (m % 2 === 0 ? 'red' : 'darkred');
var latLngs = coordinates.map(coordinate => [coordinate[1], coordinate[0]]);
L.polyline(latLngs, { color: lineColor }).addTo(osrmGeometryGroup);
for (var l = 0; l < matching.legs.length; l++) {
var leg = matching.legs[l];
var nodes = leg.annotation.nodes;
console.log('matching ' + m + ', leg ' + l + ' contains the nodes:');
console.log(nodes);
sendOverpassRequest(nodes);
}
}
}
function sendOsrmRequest() {
// get the currently displayed markers
var markers = markersGroup.getLayers();
// create an array of string: "lng,lat" with 6 digits after comma
var lngLats = markers.map(marker =>
parseFloat(marker.getLatLng().lng).toFixed(6) + ',' +
parseFloat(marker.getLatLng().lat).toFixed(6)
);
// create an array of radiuses, same length as lngLats array
var radiuses = lngLats.map(lngLat => 50);
var url = 'https://router.project-osrm.org/match/v1/driving/' +
lngLats.join(';') +
'?overview=simplified' +
'&radiuses=' +
radiuses.join(';') +
'&generate_hints=false' +
'&skip_waypoints=true' +
'&gaps=ignore' +
'&annotations=nodes' +
'&geometries=geojson';
console.log('Sending OSRM map matching query to the URL ' + url);
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.response);
processOsrmReply(data);
} else {
clearMap('OSRM error status: ' + this.status);
}
};
request.send();
}
function processOverpassReply(data) {
console.log('Received Overpass API reply with ' + data.elements.length + ' elements');
console.log(data.elements);
// get the coordinates of currently displayed markers to avoid repeated drawing
var latLngs = overpassNodesGroup.getLayers().map(marker => marker.getLatLng());
for (var n = 0; n < data.elements.length; n++) {
var element = data.elements[n];
if (element.type === 'node') {
var nodeId = element.id;
var latLng = L.latLng(element.lat, element.lon);
if (latLngs.find(pos => pos.equals(latLng))) {
console.log('The node ' + nodeId + ' is on the map already');
continue;
}
L.marker(latLng)
.bindPopup('Node id: ' + nodeId + '<br>' + latLng)
.addTo(overpassNodesGroup);
}
}
}
function sendOverpassRequest(nodes) {
var query = 'node(id:' + nodes.join(',') + '); out geom;'
console.log('Sending Overpass API query: ' + query);
var url = 'https://overpass-api.de/api/interpreter?data=[out:json];' + query;
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.response);
processOverpassReply(data);
} else {
clearMap('Overpass error status: ' + this.status);
}
};
request.send();
}
function processMapClick(ev) {
// get the currently displayed markers
var markers = markersGroup.getLayers();
if (markers.length < MARKERS_MAX) {
L.marker(ev.latlng)
.bindPopup('User marker: ' + markers.length + '<br>' + ev.latlng)
.addTo(markersGroup);
return;
}
// get the count of currently displayed polylines
var linesCount = osrmGeometryGroup.getLayers().length;
if (linesCount > 1) {
clearMap();
return;
}
sendOsrmRequest();
}
function clearMap(str = '') {
var hint = document.getElementById('hint');
hint.textContent = str;
// remove polylines and markers
osrmGeometryGroup.clearLayers();
overpassNodesGroup.clearLayers();
markersGroup.clearLayers();
}
var MARKERS_MAX = 4;
var map = L.map('map').setView([51.4661, 7.2491], 14).on('click', processMapClick);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// layer groups for markers and polylines
var markersGroup = L.layerGroup();
map.addLayer(markersGroup);
var osrmGeometryGroup = L.layerGroup();
map.addLayer(osrmGeometryGroup);
var overpassNodesGroup = L.layerGroup();
map.addLayer(overpassNodesGroup);
var overlays = {
'Show <b>markers</b> placed by user': markersGroup,
'Show <b>geometry</b> returned by OSRM': osrmGeometryGroup,
'Show <b>nodes</b> returned by Overpass': overpassNodesGroup
};
L.control.layers(null, overlays, { collapsed: false }).addTo(map);
<!-- language: lang-css -->
html,
body {
padding: 0;
margin: 0;
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
#map {
flex-grow: 1;
}
#hint {
text-align: center;
}
<!-- language: lang-html -->
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet.min.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet-src.min.js"></script>
<p id="hint">Click the map 5x to draw the map matched nodes!</p>
<div id="map"></div>
<!-- end snippet -->
[1]: https://jsfiddle.net/afarber/qeyr29sa/
[2]: https://i.stack.imgur.com/fFlr8.gif