Javascript: Strecke von A nach B in Karte anzeigen - Wie geht das?

Hallo,
ich bin Anfänger in Sachen Openstreetmap.
Ich programmiere eine progressive Web App mit HTML, CSS und Javascript.
Der Anwender soll die Möglichkeit haben, sich eine Strecke (Startort und Zielort jeweils mit Angabe des Ortes oder Postleitzahl + Strasse) sich auf der Karte anzeigen zu lassen.

Hier mein Versuch:

// Diese Funktion zeigt die Route auf der Karte an
function displayRouteOnMap(routeData, startCoordinates, endCoordinates) {
  // Konsolenausgabe zur Überprüfung der routeData
  console.log("Empfangene Routendaten:");
  console.log(routeData);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";


  map = L.map("mapid").setView(
    [
      (startCoordinates.latitude + endCoordinates.latitude) / 2,
      (startCoordinates.longitude + endCoordinates.longitude) / 2,
    ],
    10
  ); // Hier die erste Zeile für die Karte mit dem Durchschnitt der Koordinaten von Start und Ziel

  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);
  const route = L.geoJSON(routeData);
  route.addTo(map); // Hier die zweite Zeile für die Hinzufügung der Route
}




/**
 * Zeigt eine Openstreetmap-Karte an
 * @param {address} address der gesprochen werden soll.
 */

function showMapWithAddress(address) {
  let vaddress = escapeHtml(address);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  map = L.map("mapid");
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  let marker;

  function geocodeAddress(vaddress) {
    let url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(
      vaddress
    )}`;

    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        if (data.length > 0) {
          var latitude = data[0].lat;
          var longitude = data[0].lon;

          if (marker) {
            map.removeLayer(marker);
          }

          marker = L.marker([latitude, longitude]).addTo(map);

          // Setzen der Kartenposition basierend auf den geokodierten Koordinaten
          map.setView([latitude, longitude], 15);
        } else {
          alert("Geokodierung fehlgeschlagen: Adresse nicht gefunden");
        }
      })
      .catch((error) => {
        alert("Fehler bei der Geokodierung: " + error);
      });
  }

  geocodeAddress(vaddress);
}

Die Daten der Strecke, werden in der Browser-Konsole korrekt ausgegeben, aber das anzeigen der Strecke in der Karte klappt nicht.

Frage:
Wer kann mir helfen?

Hallo @pwaMarlem und willkommen hier!

Folgender Code funktioniert für mich in einer herkömmlichen Webseite für die Anzeige einer Streckevon A nach B, die als geoJSON (hier im gleichen Verzeichnis des Webservers) vorliegt mit Marker für Start- und Endpunkt. Das ganze kann man sich unter Leaflet - Route als geoJSON einbinden anschauen.

	// Funktion zum Einbinden von GeoJSON-Dateien
	// siehe Antwort von F1refly in https://gis.stackexchange.com/questions/68489/loading-external-geojson-file-into-leaflet-map
	async function getGeoJson(url) {
		const response = await fetch(url);
		const data = await response.json();
		return data;
	}	

	// Anzeige der Route - plus Start- und Endpunkt
	async function displayRoute(url, map) {
		const routeData = await getGeoJson(url);
		// falls route sonst nicht gebraucht wird:
		// L.geoJSON(routeData).addTo(map);
		const route = L.geoJSON(routeData);
		route.addTo(map);
		
		// Marker an Start und Ziel
		displayMarker(routeData, map);
	}

	// Anzeige Start- und Endpunkt auf der Basis meiner Routendaten
	function displayMarker(routeData, map) {
		// passt so bei meinen geoJSON-Daten der Route: lng, lat, height
		var startPoint = routeData.features[0].geometry.coordinates[0][0];
		var endPoint = routeData.features[0].geometry.coordinates.at(-1).at(-1);

		L.marker([startPoint[1], startPoint[0]]).addTo(map);
		L.marker([endPoint[1], endPoint[0]]).addTo(map);
	}
		
	var map = new L.map('mapid', {
		fullscreenControl: true,
		fullscreenControlOptions: {
			position: 'topleft'
		}
	} ).setView([49.20, 5.40], 9);
	
	L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
		maxZoom: 19,
		attribution: '&copy; Openstreetmap | &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
	}).addTo(map);
	
	displayRoute("./meine-route.geojson", map);	

Bei einer erneuten Sucheingabe würde ich das Map-Objekt nur an die neue Stelle verschieben statt zu löschen und wieder neu zu erzeugen.

Anmerkung: auf das {s}. beim Tilelayer kannst Du inzwischen verzichten (bzw. es ist besser, darauf zu verzichten), siehe die Beiträge #9 und #11 in A,b,c.tile.openstreetmap.de subdomains von tile.openstreetmap.de werden aufgehoben - #9 by Stereo

Was spuckt denn Deine Konsole als Fehler aus?

@Vinzenz_Mai
Vielen Dank für Deine Antwort und das teilen Deines Codes.
Leider bin ich in Sachen JS nicht so fit, dass ich genau weiß was zu tun ist.

Im Browser Google Chrome bekomme ich in der Konsole diese Fehlermeldung:
Failed to load resource: the server responded with a status of 404 (Not Found)
assistent.js:241 Empfangene Routendaten:
LatLng.js:32 Uncaught Error: Invalid LatLng object: (NaN, NaN)
at new D (LatLng.js:32:9)
at j (LatLng.js:123:11)
at i.setView (Map.js:181:30)
at displayRouteOnMap (assistent.js:253:24)
at marlemsAssistent (commandos.js:290:7)
at HTMLButtonElement. (assistent.js:122:3)
index.html:1 Access to internal resource at ‘file:///C:/Projekte/Apps/HTML/Marlems%20Assistent/manifest.webmanifest’ from origin ‘null’ has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.

Ich zitiere aus dem Wiki:

Also: Du brauchst einen lokalen Webserver, um solche Sachen auszuprobieren, Start der HTML-Datei direkt aus dem Explorer heraus funktioniert nicht. Es muss nichts kompliziertes sein, so was kleines wie tinyweb reicht aus.

Alternativ könntest Du z.B. den IIS Deines Windows-Rechners aktivieren oder XAMPP nutzen (gibt es auch als portable Version, die nicht installiert werden muss)

Hier der Link zur App: https://www.marlems-assistent.de/ .
Die Anweisung heißt “autofahren”.
Ich habe eine Funktion implementiert, die eine bestimmte Adresse anzeigt (=Ort+Strasse+Hausnummer), das funktioniert.
Nur das anzeigen einer Strecke klappt nicht.

Beim “autofahren” fehlt auf jeden Fall die Geocodierung:

/*        AUTOFAHREN   */       
   keywords = [
    /autofahren/i,
   ];
  
   matches = validateSearchQuery(userCommandstr, keywords);  
     if (matches){
      const startort = prompt("Geben Sie den Startort ein:");
      const zielort = prompt("Geben Sie den Zielort ein:");
    
      if (startort && zielort) {
      displayRouteOnMap(startort, zielort);

      } else {
        alert("Start- und Zielort müssen angegeben werden.");
      }
      responseGiven = true;
     }

Du übergibst die Texteingaben des Benutzers, typischerweise zwei Adressen, an die Funktion displayRouteOnMap, diese erwartet jedoch Koordinaten:

function displayRouteOnMap(startCoordinates, endCoordinates) {

Die Eingaben müsstest Du wie bei der Adressanzeige zuerst geocodieren lassen - und anschließend daraus die Route generieren lassen, was OSM nicht von selbst kann.

Du müsstest also einen Routingdienst befragen (oder selbst zur Verfügung stellen). Die Form der Antwort muss kein geojson sein, d.h. diese wäre entsprechend zu transformieren oder andere Funktionen zur Anzeige zu nutzen.

Vielen Dank.
Der Code hier ist von ChatGPT ohne die KI hätte ich die implemtierung gar nicht geschafft:

function showMapWithAddress(address) {
  let vaddress = escapeHtml(address);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  map = L.map("mapid");
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  let marker;

  function geocodeAddress(vaddress) {
    let url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(
      vaddress
    )}`;

    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        if (data.length > 0) {
          var latitude = data[0].lat;
          var longitude = data[0].lon;

          if (marker) {
            map.removeLayer(marker);
          }

          marker = L.marker([latitude, longitude]).addTo(map);

          // Setzen der Kartenposition basierend auf den geokodierten Koordinaten
          map.setView([latitude, longitude], 15);
        } else {
          alert("Geokodierung fehlgeschlagen: Adresse nicht gefunden");
        }
      })
      .catch((error) => {
        alert("Fehler bei der Geokodierung: " + error);
      });
  }

  geocodeAddress(vaddress);
}

Meine Lösungsidee:
geocodeAddress(vaddress) als eigene Funktion und die dann hier:

if (startort && zielort) {
     geocodeAddress(vaddress)
      displayRouteOnMap(startort, zielort);
``` aufrufen. 

Frage:
Was hältst Du davon?

… und zwar eine wiederverwertbare, die Du für den Start- und Zielpunkt und auch für die Adressanzeige verwenden kannst. Das bedeutet: Du übergibst dieser Funktion eine Adresse(genauer: einen Text) und die Funktion gibt im Erfolgsfall, wenn die Eingabe von Nominatim gefunden wurde, die Koordinaten dieser Adresse zurück, könnte z.B. so aussehen:

	async function geocodeAddress(vaddress) {
		let url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(vaddress)}`;
		var coords;

		const response = await fetch(url);
		// console.log(response);
		if (response.ok) {
			// Bis alle Daten da sind, kann es etwas dauern
			data = await response.json();
			// console.log(data);
			if (data.length > 0) {
				coords = [data[0].lat, data[0].lon];
			}
			// andernfalls nicht gefunden
		}
		return(coords);
	}

Anschließend testen, ob das auch funktioniert, z.B. einfach statisch:

 
	// Funktion zum Testen der Geocodierung
	async function main() {
		// Startpunkt (existiert)
		var startAddress = "Veledastraße 9, Köln";
		// Endpunkt (existiert nicht)
		var endAddress = "Titusweg 17, Köln";
	  
		const startCoords = await geocodeAddress(startAddress);
		console.log(startAddress);
		console.log(startCoords);

		const endCoords = await geocodeAddress(endAddress);
		console.log(endAddress);
		console.log(endCoords);
	}

	main();

Und Deine displayRoute könnte von der Logik so aussehen:

	async function displayRoute(startAddress, endAddress) {
		const startCoords = await geocodeAddress(startAddress);
		const endCoords = await geocodeAddress(endAddress);

		if (!(startCoords === undefined || endCoords === undefined)) {
			// beide Adressen konnten geocodiert werden
			// Nun brauchst Du die Routendaten
			routeData = getRoute(startCoords, endCoords);
		}
	
		// Wenn die Route erfolgreich erstellt werden konnte
			// Erzeuge passenden Kartenausschnitt
			// Erstelle Marker für Startpunkt
			// Erstelle Marker für Zielpunkt
			// Zeige die Route an
		}

Vielen Dank für Deine Erklärung!
Änderungen hochgeladen, link siehe oben.

// Diese Funktion zeigt die Route auf der Karte an
async function displayRouteOnMap(startAddress, endAddress) {
  // Konsolenausgabe zur Überprüfung der Routendaten
  console.log("Empfangene Routendaten:");

  // Geokodiere die Start- und Zieladressen
  const startCoordinates = await geocodeAddress(startAddress);
  const endCoordinates = await geocodeAddress(endAddress);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  // Zentriere die Karte basierend auf den durchschnittlichen Koordinaten von Start und Ziel
  map = L.map("mapid").setView(
    [
      (startCoordinates.latitude + endCoordinates.latitude) / 2,
      (startCoordinates.longitude + endCoordinates.longitude) / 2,
    ],
    10
  );

  // Füge OpenStreetMap-Kacheln zur Karte hinzu
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Lade die Route als GeoJSON und füge sie zur Karte hinzu
  const routeData = await getRouteData(startCoordinates, endCoordinates);
  const route = L.geoJSON(routeData);
  route.addTo(map);
}


/**
 * Zeigt eine Openstreetmap-Karte an
 * @param {address} address der gesprochen werden soll.
 */

function showMapWithAddress(address) {
  let vaddress = escapeHtml(address);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  map = L.map("mapid");
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  let marker;

  geocodeAddress(vaddress).then((coords) => {
    if (coords) {
      if (marker) {
        map.removeLayer(marker);
      }

      marker = L.marker(coords).addTo(map);

      // Setzen der Kartenposition basierend auf den geokodierten Koordinaten
      map.setView(coords, 15);
    } else {
      alert("Geokodierung fehlgeschlagen: Adresse nicht gefunden");
    }
  });
}

async function geocodeAddress(vaddress) {
  let url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(vaddress)}`;
  var coords;

  const response = await fetch(url);
  if (response.ok) {
    data = await response.json();
    if (data.length > 0) {
      coords = [data[0].lat, data[0].lon];
    }
  }
  return coords;
}

Bei async function displayRouteOnMap(startAddress, endAddress) { gibt es folgende Fehlermeldung:
LatLng.js:32 Uncaught (in promise) Error: Invalid LatLng object: (NaN, NaN)
at new D (LatLng.js:32:9)
at j (LatLng.js:123:11)
at i.setView (Map.js:181:30)
at displayRouteOnMap (assistent.js:257:24)

Was muss ich ändern?

Was ich online aufrufen kann, ist immer noch das gleiche wie gestern.

Grundsätzlich ist jedoch eine Umwandlung der Koordinaten von Zeichenketten in Kommazahlen erforderlich, am einfachsten gleich in der Geocodierung:

	// geocodeAddress
	// Übergabe: Texteingabe, idealerweise eine Adresse, mit der Nominatim was anfangen kann.
	// Rückgabe: 
	// 		- im Erfolgsfall ein Array mit Breite und Länge als Kommazahlen
	//		- im Fehlerfall (nicht gefunden oder sonstiger Fehler, z.B. nominatim nicht erreichbar) undefined
	async function geocodeAddress(vaddress) {
		let url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(vaddress)}`;
		var coords;

		const response = await fetch(url);
		// console.log(response);
		if (response.ok) {
			// Bis alle Daten da sind, kann es etwas dauern
			data = await response.json();
			// console.log(data);
			if (data.length > 0) {
				// Aus den Zeichenketten Kommazahlen machen
				coords = [parseFloat(data[0].lat), parseFloat(data[0].lon)];
			}
			// andernfalls nicht gefunden
		}
		return(coords);
	}

Die Callback-Hölle vom ChatCPT tue ich mir nicht an …

Siehe Leaflet - Zeige Start- und Endpunkt an

Kann sein Du musst den Browser-Cache leeren.
Dein Vorschlag hat geholfen.

Ich bekomme jetzt diese beiden Fehlermeldungen:
Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received

LatLng.js:32 Uncaught (in promise) Error: Invalid LatLng object: (NaN, NaN)
at new D (LatLng.js:32:9)
at j (LatLng.js:123:11)
at i.setView (Map.js:181:30)
at displayRouteOnMap (assistent.js:235:24)

Ich haben mein Codepen aktualisiert. Vielleicht ist das einfacher:

Siehe meinen Beispielcode:

Durch

	coords = [parseFloat(data[0].lat), parseFloat(data[0].lon)];

gibt es nur Array-Elemente mit numerischem Index, aber kein Objekt mit den Eigenschaften latitude oder longitude,
deswegen greife ich über

	var map = new L.map('mapid').setView(
		[
			// lat ist im ersten Array-Element
			(startCoords[0] + endCoords[0]) / 2, 
			(startCoords[1] + endCoords[1]) / 2,
		], 14
	);

auf Längen- und Breitenangabe zu. Möchtest Du ein Object mit den Properties latitude und longitude haben, dann müsstest Du die Zuweisung zur Variablen coords wie folgt verändern:

	coords = {
		latitude : parseFloat(data[0].lat),
		longitude : parseFloat(data[0].lon)
	};

Edit:
Siehe Leaflet - Zeige Start- und Endpunkt an

Entschuldigung, ich habe es nicht geblickt:

// Diese Funktion zeigt die Route auf der Karte an
async function displayRouteOnMap(startAddress, endAddress) {
  // Konsolenausgabe zur Überprüfung der Routendaten
  console.log("Empfangene Routendaten:");

  // Geokodiere die Start- und Zieladressen
  const startCoordinates = await geocodeAddress(startAddress);
  const endCoordinates = await geocodeAddress(endAddress);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  // Zentriere die Karte basierend auf den durchschnittlichen Koordinaten von Start und Ziel
  map = L.map("mapid").setView(
    [// lat ist im ersten Array-Element
			(startAddress[0] + endAddress[0]) / 2, 
			(startAddress[1] + endAddress[1]) / 2,
    ],
    10
  );

  // Füge OpenStreetMap-Kacheln zur Karte hinzu
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Lade die Route als GeoJSON und füge sie zur Karte hinzu
  const routeData = await getRouteData(startCoordinates, endCoordinates);
  const route = L.geoJSON(routeData);
  route.addTo(map);
}

Ich habe ftp und Codepen aktualisiert.
Bekomme folgende Fehlermeldung:
LatLng.js:32 Uncaught (in promise) Error: Invalid LatLng object: (NaN, NaN)
at new D (LatLng.js:32:9)
at j (LatLng.js:123:11)
at i.setView (Map.js:181:30)
at displayRouteOnMap (assistent.js:235:24)

Was habe ich vergessen?

Deine Variable heißt
startCoordinates.

Diese musst Du verwenden, nicht
startAddress.

Also:

  // Zentriere die Karte basierend auf den durchschnittlichen Koordinaten von Start und Ziel
  map = L.map("mapid").setView(
    [// lat ist im ersten Array-Element
			(startCoordinates[0] + endCoordinates[0]) / 2, 
			(startCoordinates[1] + endCoordinates[1]) / 2,
    ],
    10
  );

Danke! Die Karte wird jetzt angezeigt, aber keine Strecke in der Karte.
Änderungen per ftp hochgeladen codepen ergänzt.
Hier mein ganzer JS-Code für Openstreetmap:

async function getRouteData(startCoordinates, endCoordinates) {
  // Geokodiere die Start- und Zielkoordinaten zu Adressen
  const startAddress = await reverseGeocode(startCoordinates[0], startCoordinates[1]);
  const endAddress = await reverseGeocode(endCoordinates[0], endCoordinates[1]);

  // Anfrage-URL für die Route mit Start- und Zieladresse
  const apiUrl = `https://nominatim.openstreetmap.org/directions?format=json&geometry=geojson&origin=${encodeURIComponent(startAddress)}&destination=${encodeURIComponent(endAddress)}`;

  try {
    // Abrufen der Routendaten
    const response = await fetch(apiUrl);
    if (!response.ok) {
      throw new Error("Fehler beim Abrufen der Routendaten");
    }

    const routeData = await response.json();
    return routeData;
  } catch (error) {
    console.error(error);
    throw error;
  }
}


// Diese Funktion zeigt die Route auf der Karte an
async function displayRouteOnMap(startAddress, endAddress) {
  // Konsolenausgabe zur Überprüfung der Routendaten
  console.log("Empfangene Routendaten:");

  // Geokodiere die Start- und Zieladressen
  const startCoordinates = await geocodeAddress(startAddress);
  const endCoordinates = await geocodeAddress(endAddress);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  // Zentriere die Karte basierend auf den durchschnittlichen Koordinaten von Start und Ziel
  map = L.map("mapid").setView(
    [// lat ist im ersten Array-Element
			(startCoordinates[0] + endCoordinates[0]) / 2, 
			(startCoordinates[1] + endCoordinates[1]) / 2,
    ],
    10
  );

  // Füge OpenStreetMap-Kacheln zur Karte hinzu
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Lade die Route als GeoJSON und füge sie zur Karte hinzu
  const routeData = await getRouteData(startCoordinates, endCoordinates);
  const route = L.geoJSON(routeData);
  route.addTo(map);
}


/**
 * Zeigt eine Openstreetmap-Karte an
 * @param {address} address der gesprochen werden soll.
 */

function showMapWithAddress(address) {
  let vaddress = escapeHtml(address);

  // Überprüfe, ob das map-Objekt bereits existiert
  if (typeof map !== "undefined") {
    map.off();
    map.remove();
  }

  map = L.map("mapid");
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution:
      '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
  }).addTo(map);

  // Setze das Karten-DIV sichtbar
  mapidDiv.style.display = "block";

  let marker;

  geocodeAddress(vaddress).then((coords) => {
    if (coords) {
      if (marker) {
        map.removeLayer(marker);
      }

      marker = L.marker(coords).addTo(map);

      // Setzen der Kartenposition basierend auf den geokodierten Koordinaten
      map.setView(coords, 15);
    } else {
      alert("Geokodierung fehlgeschlagen: Adresse nicht gefunden");
    }
  });
}

async function geocodeAddress(vaddress) {
  let url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(vaddress)}`;
  var coords;

  const response = await fetch(url);
  if (response.ok) {
    data = await response.json();
    if (data.length > 0) {
      // Aus den Zeichenketten Kommazahlen machen
				coords = [parseFloat(data[0].lat), parseFloat(data[0].lon)];
    }
  }
  return coords;
}

/**
 * Ruft Ortsnamen anhand von Latitude und Longitude ab und zeigt sie in der App an
 * @param {number} latitude - Breitengrad
 * @param {number} longitude - Längengrad
 */

function reverseGeocode(latitude, longitude, callback) {
  const url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&zoom=18&addressdetails=1`;

  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      if (data.display_name) {
        const addressComponents = data.display_name.split(", ");
        const locationName = addressComponents[addressComponents.length - 3];
        callback(locationName);
      } else {
        console.error("Reverse-Geokodierung fehlgeschlagen");
        callback(null);
      }
    })
    .catch((error) => {
      console.error("Fehler bei der Reverse Geokodierung: " + error);
      callback(null);
    });
}

async function getRouteData(startCoordinates, endCoordinates) { soll die Daten in der Karte anzeigen, aber das klappt nicht.

Wie funktioniert es?

Wie ich schon schrieb:

Für die OSRM-Routing-Engine gibt es einen Demo-Server, vom FOSSGIS gesponsort, hier die Nutzungsbedingungen.

Die API-Dokumentation findet sich unter OSRM API Documentation

Damit kann man folgende Funktion implementieren (Demo, ohne echte Fehlerbehandlung):

	// OSRM will Koordinaten haben: long,lat;long,lat; ...
	async function getRouteData(start, ende) {
	
		// Ermittle Route zwischen Start- und Endpunkt
		// Hier verwendet: Demo-Server on OSRM
		// API siehe https://project-osrm.org/docs/v5.5.1/api/#general-options
		const apiUrl = `https://router.project-osrm.org/route/v1/car/${encodeURIComponent(start[1])},${encodeURIComponent(start[0])};${encodeURIComponent(ende[1])},${encodeURIComponent(ende[0])}?geometries=geojson&overview=simplified`;

		// Abrufen der Routendaten
		const response = await fetch(apiUrl);
		if (!response.ok) {
		  throw new Error("Fehler beim Abrufen der Routendaten");
		}
		const routeData = await response.json();		
		return(routeData);
	}

Der Aufruf in displayRouteData() könnte wie folgt aussehen:

  const routeData = await getRouteData(startCoordinates, endCoordinates);
  console.log(routeData);
  // Das GeoJSON-Objekt mit der Route befindet sich in den route-Elementen in geometry
  // Grundsätzlich kann OSRM auch alternative Routen zurückliefern, dann gibt es mehr als ein Array-Element.
  const geometry = routeData.routes[0].geometry;
  const route = L.geoJSON(geometry);
  route.addTo(map);

Eine funktionierende Demo (ohne Fehlerbehandlung) findest Du unter https://leaflet-examples.4lima.de/route-osrm-demo.html

Bitte beachte, dass ich noch weiter Korrekturen im Code vorgenommen habe, z.B. ist map jetzt eine globale Variable, damit man sich auch mehr als einmal eine Route anzeigen lassen kann, mit dem map.off();map.remove();, das bereits in Deiner Originalversion von ChatCPT vorhanden war.

Danke!
Das was die Demo kann: Leaflet - Route mit OSRM (Demo-Server) , dass möchte ich können.
Aber ich weiß nicht ob ich es blicke, dass in meiner App zu übernehmen.
Es ist alles so komplex …

Du bist doch schon fast durch - und den in den letzten Tagen natürlich gewachsenen (sprich nicht sonderlich strukturierten) Code kann und sollte man etwas aufräumen, was für bessere Verständlichkeit hilft.

Zusammenfassung:
Die Hauptfunktion displayRoute(),
der die Benutzereingaben von Start- und Zielort als Adressen übergeben werden, benötigt zwei Hilfsfunktionen

  1. geocodeAddress(),
    die eine Adresse von Nominatim in Geokoordinaten umwandeln lässt.
  2. getRouteData(),
    die von einem Routingdienst die Route zwischen Start- und Zielkoordinaten ermittlen lässt.

Die Hauptfunktion displayRoute() lässt sich in die Abschnitte unterteilen

  • Lasse Start- und Zieladresse geocodieren
  • Aufräumen, falls notwendig
  • Lasse Route zwischen Start und Ziel ermitteln
  • Stelle das auf der Karte dar:
    1. Geeigneter Ausschnitt
    2. Setze Marker für Start und Ziel
    3. Zeige Route an
    4. Optional: Passe Karte an die Anzeigedaten an
	async function displayRoute(startAddress, endAddress) {
		//Geocodiere Start- und Zieladresse 
		const startCoordinates = await geocodeAddress(startAddress);
		const endCoordinates = await geocodeAddress(endAddress);

		// Wenn erfolgreich
		if (!(startCoordinates === undefined || endCoordinates === undefined)) {
			// -------------------------------
			// Räume auf, falls notwendig
			// Map-Objekt
			if (typeof map !== "undefined") {
				map.off();
				map.remove();
			} 
			// Marker
			if (markerStart) {
				map.removeLayer(markerStart);
			}
			if (markerZiel) {
				map.removeLayer(markerZiel);
			}
			// Markergruppe
			if (group) {
				map.removeLayer(group);
			}

			// -------------------------------
			// Route ermitteln
			const routeData = await getRouteData(startCoordinates, endCoordinates);

			// -------------------------------
			// Darstellung auf der Karte
			// Passender Kartenbereich vorbereiten 
			map = L.map('mapid').setView(
				[
					// lat ist im ersten Array-Element
					(startCoordinates[0] + endCoordinates[0]) / 2, 
					(startCoordinates[1] + endCoordinates[1]) / 2,
				], 14
			);
			
			// Kartenkacheln laden
			L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
				maxZoom: 19,
				attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, <a  href="https://openstreetmap.org/fixthemap">mitmachen/Fehler melden</a>'
			}).addTo(map);
			
			// Marker für Start und Zieladresse und gruppiere diese			
			var markerStart = L.marker([startCoordinates[0], startCoordinates[1]]).addTo(map);
			var markerZiel = L.marker([endCoordinates[0], endCoordinates[1]]).addTo(map);
			var group = new L.featureGroup([markerStart, markerZiel]);

			// Zeige Routendaten an
			const geometry = routeData.routes[0].geometry; 
			const route = L.geoJSON(geometry);
			route.addTo(map);
			
			// Passe die Anzeige an das Notwendige an
			map.fitBounds(group.getBounds());
		}
	}