Vektorkacheln in Leaflet
Leaflet zeigt Kartenbilder und kann keine Vektorkacheln mit einem Stil zeichnen. Das Plugin maplibre-gl-leaflet setzt eine MapLibre-Karte als Layer in Leaflet, Ihre Leaflet-Marker, Popups und GeoJSON bleiben also, wie sie sind. Mit Script-Tags und mit einem Bundler. Getestet mit Leaflet 1.9.4 und maplibre-gl-leaflet 0.1.4.
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/@maplibre/maplibre-gl-leaflet@0.1.4/leaflet-maplibre-gl.js"></script>
<style>#map { height: 480px; }</style>
<div id="map"></div>
<script>
const map = L.map("map").setView([47.37, 8.54], 13);
L.maplibreGL({
style: "https://api.overpass.ch/v1/IHR_SCHLÜSSEL/maps/styles/light.json?lang=de"
}).addTo(map);
</script>
Mit Script-Tags
Das Plugin braucht den klassischen Build von MapLibre, der mit einem Tag <script src> lädt und maplibregl definiert. MapLibre 6 gibt es nur als ES-Module, Script-Tags verwenden also MapLibre 5; Version 5.24.0 ist die letzte. Leaflet-Layer kommen wie gewohnt über die Vektorkarte:
const map = L.map("map").setView([47.37, 8.54], 13);
const base = L.maplibreGL({
style: "https://api.overpass.ch/v1/IHR_SCHLÜSSEL/maps/styles/light.json?lang=de"
}).addTo(map);
L.marker([47.3769, 8.5417]).addTo(map).bindPopup("Zürich HB").openPopup();
L.geoJSON(route, { style: { color: "#d0312d", weight: 4 } }).addTo(map);
Jeder unserer neun Stile funktioniert: light, dark, white, grayscale, black, outdoor, marine, relief und driving. Ergänzen Sie &hillshade=1 für die Schummerung. Leaflet kann die Karte nicht neigen, terrain=1 nützt hier also nichts.
Mit einem Bundler und MapLibre 6
npm install leaflet maplibre-gl @maplibre/maplibre-gl-leaflet
Das lief in einem Build mit Vite 8 und MapLibre 6.13.0:
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import "maplibre-gl/dist/maplibre-gl.css";
import { setWorkerUrl } from "maplibre-gl";
import workerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url";
import { maplibreGL } from "@maplibre/maplibre-gl-leaflet";
import markerIcon from "leaflet/dist/images/marker-icon.png";
import markerIcon2x from "leaflet/dist/images/marker-icon-2x.png";
import markerShadow from "leaflet/dist/images/marker-shadow.png";
setWorkerUrl(workerUrl);
// der Bundler verschiebt die Marker-Bilder: sagen Sie Leaflet, wo sie sind
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({ iconUrl: markerIcon, iconRetinaUrl: markerIcon2x, shadowUrl: markerShadow });
const KEY = import.meta.env.VITE_OVERPASS_KEY;
const map = L.map("map").setView([47.37, 8.54], 13);
maplibreGL({
style: `https://api.overpass.ch/v1/${KEY}/maps/styles/light.json?lang=en`
}).addTo(map);
L.marker([47.3769, 8.5417]).addTo(map).bindPopup("Zürich HB").openPopup();
Zwei Stellen beheben die Fehler, auf die wir unterwegs gestossen sind:
- Ohne
setWorkerUrlbleibt die Karte leer, und die Konsole zeigt «Worker failed to load. Check that the worker URL is correct.» MapLibre 6 braucht den Aufruf mit jedem Bundler; für webpack siehe die Anleitung zum Umstieg auf MapLibre. - Ohne die Marker-Bilder sind Marker unsichtbar, und der Netzwerk-Tab zeigt 404 für
marker-icon.pngundmarker-shadow.png. Das ist ein Problem von Leaflet mit jedem Bundler.
Die MapLibre-Karte darin
getMaplibreMap() gibt die MapLibre-Karte zurück, für alles, was Leaflet nicht kann, etwa einen Layer mit Höhenlinien oder einen Klick auf ein Objekt der Grundkarte:
const gl = base.getMaplibreMap();
gl.on("load", () => {
gl.addSource("contours", { type: "vector", url: "https://api.overpass.ch/v1/IHR_SCHLÜSSEL/maps/contours.json" });
gl.addLayer({ id: "contours", type: "line", source: "contours", "source-layer": "contours",
paint: { "line-color": "rgba(124, 92, 58, 0.5)" } });
});
Die Zoomstufen unterscheiden sich um eins: Leaflet-Zoomstufe 13 ist MapLibre-Zoomstufe 12, weil MapLibre mit Kacheln von 512 Pixeln rechnet. Das Plugin rechnet zwischen ihnen um.
Grenzen
- Leaflet kann die Karte weder neigen noch drehen. Für 3D-Gelände oder eine drehbare Karte verwenden Sie MapLibre GL JS direkt: Aus
L.markerwirdmaplibregl.Marker, und GeoJSON-Layer werden zu Quellen und Layern. - overpass.ch hat keine Kartenbilder als PNG. Für einen einfachen Layer mit Bildkacheln verwenden Sie einen Rasterkachel-Dienst.
- Ihr Schlüssel ist in der Seite sichtbar. Erstellen Sie in Ihrem Dashboard einen Schlüssel vom Typ «Nur Karten», und tragen Sie Ihre Website als erlaubten Referer ein, dazu
localhost:5173für den Entwicklungsserver von Vite. - Kacheln zählen wie bei MapLibre: eine Kartenkachel pro Vektorkachel. Jedes Konto enthält 100'000 im Monat.