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

Hallo,

a) sowohl auf der Website als auch in codepen.io finde ich die Funktion displayRouteOnMap zweimal.
Bitte die erste löschen

b) getRouteData ist noch die alte Version, die versucht die Daten von Nominatim zu bekommen. Diese API gibt es nicht. Durch die Version in Beitrag #17 ersetzen, denn die zweite Version von displayRouteOnMap() funktioniert nur mit der OSRM-API, die erste gar nicht.

// 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);
	}

c) Wenn ich den Code der Reverse-Geocodierung in einer separaten HTML-Datei nutze, funktioniert dieser ohne Fehlermeldung.

Hallo,
Vielen Dank für die Hilfe!
Codepen aktualisiert per FTP Dateien hochgeladen.
Die gute Nachricht ist, ich bekomme in der Browser-Konsole keine Fehlermeldung.
Die schlechte Nachricht ist, die Karte und die Route wird nicht angezeigt.

Weißt Du woran es liegt?

Hallo,

ich vermute, ja: Dein div-Element, in dem die Karte angezeigt werden soll, ist versteckt, meins war es nicht. Deswegen wieder

in displayRouteOnMap ergänzen.

Du Held! Es funktioniert.
Codepen aktualisiert. Per FTP hochgeladen.

Allerdings wird die Karte von der Y-Position zu weit unten angezeigt.
Frage:
Wie kann ich das ändern?

:slight_smile:

Das ist in Deinem HTML-Code folgender Abschnitt:

<div id="parentElement">
      <div id="response"></div>
      <div id="mapid"></div>
</div>

Was die Karte nach unten schiebt, ist das div-Element mit id="response" Ich vermute, dass Du das so nicht willst, sondern, dass die Karte Inhalt dieses Elementes ist. In diesem Falle wäre

<div id="parentElement">
      <div id="response">
            <div id="mapid"></div>
      </div>
</div>

das Richtige.

Wenn das nicht der Fall ist, dann müsstest Du das response-DIV ausblenden (und wenn Du es wieder brauchst wieder einblenden). Das geht prinzipiell genauso, wie Du das Einblenden (das ich vergessen hatte) vom Kartenelement machst.

@Vinzenz_Mai
Du bist ein Held!
Es funktioniert auch auf meinem Smartphone.
Ich musste das div so ausblenden:

responseDiv.style.display = "none";

Hier nochmal der ganze Code:

// 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);
}


async function displayRouteOnMap(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);

    // -------------------------------
    responseDiv.style.display = "none";
    // Setze das Karten-DIV sichtbar
    mapidDiv.style.display = "block";
    // 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());
  }
}


/**
 * 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);
      }
      responseDiv.style.display = "none";
      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)}`;
  let 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);
    });
}

Vielen, vielen vielen Dank für Deine Erklärungen und Deine Geduld!