Anleitung

MapLibre GL JS: Anleitung für die erste Karte

MapLibre GL JS zeichnet Vektorkarten mit WebGL im Browser, nach einem Stil, der Kacheln, Farben, Schriften und Symbole festlegt. Eine Karte mit unseren Kacheln, Marker und Popups, Ihre eigenen Daten als Layer, andere Stile und Sprachen, und die Bedienelemente. Mit Script-Tags und mit Vite. Getestet mit MapLibre GL JS 6.16.0.

Eine ganze Seite, mit MapLibre von einem CDN:
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@6.16.0/dist/maplibre-gl.css">
<style>#map { height: 480px; }</style>
<div id="map"></div>
<script type="module">
import * as maplibregl from "https://unpkg.com/maplibre-gl@6.16.0/dist/maplibre-gl.mjs";

const map = new maplibregl.Map({
  container: "map",
  style: "https://api.overpass.ch/v1/IHR_SCHLÜSSEL/maps/styles/light.json?lang=de",
  center: [8.54, 47.375], // Länge, Breite
  zoom: 13
});
map.addControl(new maplibregl.NavigationControl());
</script>
Die Karte wird geladen…
Der Marker und der Layer mit den Läden aus dem Code unten. Klicken Sie auf den Marker oder einen roten Punkt und wechseln Sie dann den Stil: Der Layer bleibt.

Mit Script-Tags

MapLibre 6 gibt es nur als ES-Module: Laden Sie es in einem <script type="module"> mit einem Import von einem CDN, und legen Sie die Version fest. Die CSS-Datei platziert Bedienelemente, Marker und Popups; ohne sie verlieren diese ihre Position. Für ein klassisches <script src> verwenden Sie MapLibre 5, die letzte Version mit diesem Build: maplibre-gl@5.24.0/dist/maplibre-gl.js legt die globale Variable maplibregl an.

Der Mittelpunkt ist [Länge, Breite], umgekehrt als in Leaflet. MapLibre zählt Zoomstufen in Kacheln von 512 Pixeln; Zoomstufe 12 in MapLibre zeigt deshalb das Gebiet von Zoomstufe 13 in Leaflet und OpenLayers.

Mit npm und Vite

npm install maplibre-gl

Das lief in einem Build mit Vite 8.3:

import "maplibre-gl/dist/maplibre-gl.css";
import { Map, NavigationControl, setWorkerUrl } from "maplibre-gl";
import workerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url";

setWorkerUrl(workerUrl);

const KEY = import.meta.env.VITE_OVERPASS_KEY;

const map = new Map({
  container: "map",
  style: `https://api.overpass.ch/v1/${KEY}/maps/styles/light.json?lang=de`,
  center: [8.54, 47.375],
  zoom: 13,
});
map.addControl(new NavigationControl());
  • MapLibre liest die Kacheln in einem Web Worker. Mit einem Bundler findet MapLibre 6 die Worker-Datei nicht selbst: Ohne setWorkerUrl bleibt die Karte leer, und die Konsole zeigt «Worker failed to load. Check that the worker URL is correct.» Für webpack siehe die Anleitung zum Umstieg auf MapLibre.
  • Vite liest VITE_OVERPASS_KEY aus einer Datei .env neben package.json. Der Schlüssel landet trotzdem im JavaScript der Seite; beschränken Sie ihn deshalb auf Ihre Website (unten).

Marker und Popups

new maplibregl.Marker({ color: "#d0312d" })
  .setLngLat([8.5402, 47.3782])
  .setPopup(new maplibregl.Popup({ offset: 25 }).setText("Zürich HB"))
  .addTo(map);

Ein Marker ist ein HTML-Element über der Karte: Ein Klick öffnet sein Popup, und er bleibt, wenn der Stil wechselt. Für Hunderte von Punkten zeichnen Sie diese besser als Layer, wie im nächsten Abschnitt.

Ihre Daten als Layer

function addShops() {
  map.addSource("shops", { type: "geojson", data: "shops.geojson" });
  map.addLayer({
    id: "shops",
    type: "circle",
    source: "shops",
    paint: { "circle-radius": 7, "circle-color": "#d0312d", "circle-stroke-width": 2, "circle-stroke-color": "#fff" }
  });
}
map.on("style.load", addShops);

map.on("click", "shops", (e) => {
  new maplibregl.Popup().setLngLat(e.lngLat).setText(e.features[0].properties.name).addTo(map);
});
map.on("mouseenter", "shops", () => { map.getCanvas().style.cursor = "pointer"; });
map.on("mouseleave", "shops", () => { map.getCanvas().style.cursor = ""; });
  • data nimmt eine URL oder ein GeoJSON-Objekt, mit Koordinaten in Länge und Breite.
  • Fügen Sie Quellen und Layer in style.load hinzu, nicht in load. load kommt nur einmal, und map.setStyle entfernt Ihre Layer mit dem alten Stil; wir haben geprüft, dass der Layer nach einem Wechsel von Light zu Dark fehlt. style.load kommt bei jedem Stil, der Layer kehrt also zurück.
  • map.on("click", "shops", …) reagiert nur auf Objekte dieses Layers, und e.features enthält sie.

Andere Stile, Sprachen und Dunkelmodus

const style = (name) => `https://api.overpass.ch/v1/IHR_SCHLÜSSEL/maps/styles/${name}.json?lang=de`;
const dark = matchMedia("(prefers-color-scheme: dark)").matches;

const map = new maplibregl.Map({
  container: "map",
  style: style(dark ? "dark" : "light"),
  center: [8.54, 47.375],
  zoom: 13
});

// später, zum Beispiel von einer Schaltfläche:
map.setStyle(style("outdoor"));

Es gibt neun Stile: Light, Dark, White, Grayscale und Black von Protomaps, und unsere eigenen Outdoor, Marine, Relief und Driving, zu sehen auf der Seite Kartenkacheln. lang legt die Sprache der Beschriftung fest; die 41 Sprachen stehen in der Dokumentation.

Bedienelemente

map.addControl(new maplibregl.NavigationControl({ visualizePitch: true }));
map.addControl(new maplibregl.GeolocateControl({ trackUserLocation: true }));
map.addControl(new maplibregl.ScaleControl({ unit: "metric" }));
map.addControl(new maplibregl.FullscreenControl());

Die Quellenangaben in der Ecke kommen mit der Karte. Lassen Sie sie stehen: Die OpenStreetMap-Lizenz verlangt die Quellenangabe.

Schummerung, 3D-Gelände und Höhenlinien

const map = new maplibregl.Map({
  container: "map",
  style: "https://api.overpass.ch/v1/IHR_SCHLÜSSEL/maps/styles/outdoor.json?terrain=1",
  center: [7.6586, 45.9763], // das Matterhorn
  zoom: 12.5,
  pitch: 70,
  maxPitch: 85
});

terrain=1 fügt jedem Stil 3D-Gelände hinzu, hillshade=1 eine Schummerung. Die Einzelheiten stehen in den Anleitungen zu 3D-Gelände, Schummerung und Höhenlinien; ganze Karten in einer Wanderkarte und einer Seekarte.

Ihr Schlüssel und was zählt

  • 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:5173 für den Entwicklungsserver von Vite.
  • Jede Vektor- und Geländekachel zählt als eine Kartenkachel; Stile, Schriften, Symbole und Kacheln, die der Browser schon hat, sind kostenlos. Jedes Konto enthält 100'000 Kartenkacheln im Monat.

Andere Bibliotheken

Dieselbe Karte in Leaflet und OpenLayers, als React-Komponente mit react-map-gl, und die Änderungen für Code, der für Mapbox GL JS geschrieben wurde. Wie sich die drei Bibliotheken unterscheiden: MapLibre vs. Leaflet vs. OpenLayers.