Leaflet: Boundary Grenze anzeigen XML? GeoJSON? Shapefile?

Ich möchte in Leaflet eine Grenze anzeigen, beispielsweise die Landesgrenze von Deutschland (Relation 51477) oder die Gemeinde Dierfeld (Relation 1258888)

Dazu möchte ich die Datei lokal speichern und in einem Layer anzeigen.

  • Welches Format ist wozu besser: XML? GeoJSON? Shapefile?

Ein Polygon aus Einzelkoordinaten kann ich anzeigen:

var polygon = L.polygon(
        [
          [50.27264, 7.26469],
          [51.27264, 7.26469],
          [51.27264, 6.26469],
        ],
        {
          color: '#FF6200', //Grenz-orange
          weight: 4,
          fillColor: 'none',
        }).addTo(map)
  • Wie mache ich das mit einer Datei?

Wenn es nur wenig ist, ist das einfachste das GeoJSON direkt ins Javascript zu packen. Wenn es etwas mehr ist, müsstest du das GeoJSON etwa mittels AJAX laden. Wenn es viele Megabyte sind und verschiedene Zoomstufen gibt, solltest du Vektorkacheln erstellen.

Hallo Leo, Ok, also GeoJSON? Mein erster Versuch soll Deutschland sein. Overpass macht eine Datei mit 13.646 MB. Das mag ich nicht in den Code schreiben. Wie könnte man die Daten als Datei aufrufen? Ajax kenne ich nicht. Wie würde ein entsprechender Codeblock aussehen?

“Vektor” kenne ich von SVG-Bildern in Mediawiki. Kann man ein Grenzpolygon als “Vektor” in einem Layer über die Basiskarte legen? Wie? Wie würde ein entsprechender Codeblock in Leaflet aussehen? Kann man dazu das GeoJSON direkt verwenden? oder muss man das in ein anderes Format transformieren? wie?

Hallo Markus,

administrative Grenzen kann man unter https://osm-boundaries.com/ herunterladen.
Anmeldung dort über OAuth2, d.h. mit dem OSM-Account erforderlich, um den Download machen zu können.
Mit der empfohlenen Vereinfachung wird die administrative Grenze von Deutschland als GeoJSON weniger als 100 kB klein.

Beste Grüße
Vinzenz

Cool! - aber irgendwas funktioniert nicht…
Was ich gemacht habe:
Einloggen, auf der Karte DE auswählen, wird angezeigt, Download: z=5-12, Simlify=1.
Download bringt eine geojson.gz mit 63 Bytes, entzippt mit 7-ZIP 49 Bytes, öffnen mit Notepad++:
{“type” : “FeatureCollection”, “features” : null}
… was mache ich falsch?

Wenn Ich’s richtig verstehe, hast Du den Admin-Level-Bereich auf 5 bis 12 eingeschränkt. Das wäre der Fehler. Entweder Admin-Level 2 bis Admin-Level 2 für Deutschland, bei mir hat es aber auch mit der Vorgabe Min und Max funktioniert, Simplify “Very little” ergibt ein sehr gutes Ergebnis:

Für Dierfeld: Admin-Level 8 bis 8 und keine Vereinfachung.
Die entpackten Downloads in deutschland.geojson und dierfeld.geojson umbenannt, ins gleiche Verzeichnis wie die (folgende) HTML-Datei kopiert, sieht ganz gut aus (mit der neuesten Version aus Loading external GeoJSON file into Leaflet map? - Geographic Information Systems Stack Exchange)

<!DOCTYPE html>
<html>
<head>
	<title>Leaflet - Deutschland und Dierfeld</title>
	<meta charset="utf-8" />
	
	<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
     integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
     crossorigin=""/>	
	<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
     integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
     crossorigin=""></script>
	
	<style type="text/css">
		th, td {
			text-align:right;
			font-family: Arial, Helvetica, sans-serif;
		}
		h1, p {
			font-family: Arial, Helvetica, sans-serif;
		}
	</style>
</head>
<body>
<h1>Deutschland - Beispiel</h1>
<div id="mapid" style="width: 1000px; height: 800px;"></div>

<script>

	// Für Deutschland (blauer Rahmen)
	function style(feature) {
		return {
			weight: 2,
			opacity: 1,
			color: 'blue',
			fillOpacity: 0.1
		};
	}

	// Für Dierfeld (roter Rahmen, grüne Füllung)
	function style2(feature) {
		return {
			fillColor: 'green',
			weight: 2,
			opacity: 1,
			color: 'red',
			fillOpacity: 0.3
		};
	}
	
	// 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 addGeoJson(url, mystyle) {
		const response = await fetch(url);
		const data = await response.json();
		L.geoJson(data, mystyle).addTo(mymap);
	}	
	
	// Erzeuge ein Map-Objekt. Zoomstufe und Zentrum so gewählt, dass Dierfeld und die deutsche Grenze zu sehen sind 
	var mymap = new L.map('mapid').setView([50.20, 6.80], 10);

	// und füge einen Tile-Layer hinzu
	L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {	
	L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
		maxZoom: 19,
		attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
	}).addTo(mymap);

	addGeoJson("./deutschland.geojson", {style: style});
	addGeoJson("./dierfeld.geojson", {style: style2});
	
</script>

</body>
</html>
1 Like

Jetzt auch online zu sehen: Leaflet - Deutschland und Dierfeld
Minimales Javascript ohne zusätzliche Bibliotheken (außer Leaflet selbst) und sogar ohne Leaflet-Plugins :slight_smile:

GeoJSON-Dateien können selbstverständlich mehrere Elemente enthalten, z.B. die Daten mehrerer Gemeinden. Für das nächste Beispiel habe ich in einem Download neben Dierfeld noch die Gemeinden Platten und Bengel ausgewählt. Das Ergebnis ist eine Datei in folgender Form:

{
	"type": "FeatureCollection",
	"features": [
		{
			"type": "Feature",
			"geometry": {
				"type": "Polygon",
				"coordinates": [ ... ] // Grenzpunkte von Platten
			},
			"properties": {
				"osm_id": -1259127,
				"boundary": "administrative",
				"admin_level": 8,
				"parents": "-661037,-62668,-62341,-51477",
				"name": "Platten",
				"local_name": "Platten",
				"name_en": null
			}
		},
		{
			"type": "Feature",
			"geometry": {
				"type": "Polygon",
				"coordinates": [ ... ] // Grenzpunkte von Dierfeld
			},
			"properties": {
				"osm_id": -1258888,
				"boundary": "administrative",
				"admin_level": 8,
				"parents": "-661037,-62668,-62341,-51477",
				"name": "Dierfeld",
				"local_name": "Dierfeld",
				"name_en": null
			}
		},
		{
			"type": "Feature",
			"geometry": {
				"type": "Polygon",
				"coordinates": [ ... ] // Grenzpunkte von Bengel
			},
			"properties": {
				"osm_id": -1258636,
				"boundary": "administrative",
				"admin_level": 8,
				"parents": "-3861699,-62668,-62341,-51477",
				"name": "Bengel",
				"local_name": "Bengel",
				"name_en": null
			}
		}
	]
}

Über die Angabe features.properties.name kann man auf den Namen der Gemeinde zugreifen, über features.properties.local_name auf die Eigenschaft local_name …
Mit Hilfe einer kleinen Funktion und einem entsprechend geänderten Aufruf zum Einbinden der GeoJSON-Datei kann man jede Gemeinde mit einem Popup ausstatten:

	// Ausstatten jeder Gemeinde mit einem Popup, das den Namen der Gemeinde anzeigt
	function onEachFeature(feature, layer)  {
		var popupContent = "<p style='font-weight:bold;'>" + feature.properties.name + "</p>";			
		layer.bindPopup(popupContent);
	}

    ...
	addGeoJson("./dierfeld-platten-bengel.geojson", {onEachFeature: onEachFeature, style: style2});

Weblink zum Beispiel: Leaflet - Platten, Dierfeld und Bengel