
📍 So fügen sie mehrere benutzerdefinierte marker mit einer legende zu Google Maps hinzu
Markierungen sind die primäre Methode, um einen Punkt auf einer Karte anzuzeigen. Die standardmäßige rote Google-Maps-„Stecknadel" ist zwar erkennbar, aber sobald Sie fünf Punkte unterschiedlichen Typs haben, verlieren Betrachter den Überblick: Welcher Punkt markiert eine exakte Adresse und welcher eine ungefähre Landmarke?
Das passiert ständig: ein Filialverzeichnis, unterteilt in „eigene" und „Partner"-Standorte, eine Lieferkarte mit Zonen, ein Logistik-Dashboard mit Frachttypen. Überall dort, wo Sie mehr als drei Punkte mit unterschiedlicher Bedeutung haben, entsteht ohne individuelle Icons und eine Legende Chaos.
Die Lösung sind benutzerdefinierte Marker-Icons und eine Legende, die jedes Symbol erklärt. In 20 Minuten erstellen Sie eine Karte mit mehreren Markertypen, und Nutzer verstehen auf den ersten Blick, was was ist. In der Praxis sehen wir immer wieder, dass ein paar unterschiedliche Pins und ein Legendenblock in der Ecke den Nutzern Minuten des Rätselratens und den Support-Teams Dutzende von Fragen wie „Was bedeutet der blaue Kreis?" ersparen.
Nachfolgend eine schrittweise Aufschlüsselung mit reinem JavaScript, ohne Frameworks. Wir verwenden Koordinaten rund um den Eiffelturm, eine praktische Landmarke mit gut erkennbarer Geometrie. Der Code ist bewusst minimal gehalten, jede Methode wird Zeile für Zeile erklärt, sodass Sie ihn an Ihre Aufgabe anpassen können, ohne die gesamte Dokumentation lesen zu müssen.
Der Stoff schreitet vom Einfachen zum Komplexen fort: Zuerst besorgen Sie einen API-Schlüssel und rendern eine Basiskarte, dann fügen Sie Marker mit unterschiedlichen Icons hinzu, erstellen eine Legende und haben schließlich eine funktionierende HTML-Datei, die direkt lauffähig ist. Alle Beispiele wurden in Google Chrome 120+, Firefox 121+ und Safari 17+ getestet.
💡 Kurzüberblick:
- Besorgen Sie einen Google Maps API-Schlüssel und binden Sie die Bibliothek ein
- Bereiten Sie ein Array von Punkten im JSON-Format vor: Name, Koordinaten, Typ (exakt/ungefähr)
- Weisen Sie jedem Typ über die Eigenschaft
iconein eigenes Icon zu - Erstellen Sie die Legende als HTML-Element und hängen Sie sie über
map.controlsan die Karte an - Ergebnis: eine Karte, zwei visuelle Markertypen, Legende in der oberen rechten Ecke
Einen Google Maps API-Schlüssel beziehen
Die Arbeit mit der JavaScript Maps API erfordert einen Schlüssel. Falls Sie keinen haben, erstellen Sie ihn in der Google Cloud Console.
Kurzanleitung: Rufen Sie die Console auf, erstellen Sie ein Projekt (oder wählen Sie ein bestehendes aus), aktivieren Sie die Maps JavaScript API und generieren Sie einen Schlüssel. Für die lokale Entwicklung genügt es, den Schlüssel per HTTP-Referrer einzuschränken; für den Produktivbetrieb fügen Sie Ihre Domain der Zulassungsliste hinzu. In realen Projekten legen wir für jede Anwendung stets einen separaten Schlüssel an: So lassen sich Kontingente in der Cloud Console besser nachverfolgen und der Zugriff bei einem kompromittierten Schlüssel gezielt entziehen.
Die Einbindung der Bibliothek erfolgt mit einer Zeile im <script>-Tag:
1 <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=drawMap"></script>
Das Attribut callback legt fest, welche Funktion nach dem Laden der API ausgeführt wird. Diese schreiben wir als Nächstes.

Wichtig: Seit Februar 2024 ist die Klasse
google.maps.Markeroffiziell als veraltet (deprecated) gekennzeichnet. Sie wurde durchgoogle.maps.marker.AdvancedMarkerElementersetzt, das eine bessere Performance bietet und benutzerdefiniertes HTML unterstützt. Der nachfolgende Code verwendet den klassischenMarker(er funktioniert weiterhin und ist für den Einstieg einfacher), und der FAQ-Abschnitt enthält einen Link zur Migrationsanleitung für den Wechsel zu AdvancedMarkerElement.
Karte initialisieren und Daten vorbereiten
Zunächst ein Container für die Karte und ein Array mit Koordinaten. Verwenden Sie beliebige Koordinaten; hier haben wir fünf Punkte rund um den Eiffelturm in Paris, drei exakte und zwei ungefähre.
1 <div id="mapCanvas"></div>
Wir verpacken die Daten in einem Array aus Objekten. Das Feld is_exact trennt die Marker in zwei Typen: solche, die eine exakte Adresse punktgenau markieren, und solche, die ein ungefähres Gebiet anzeigen.
1 const locations = [ 2 { name: "Eiffel Tower", lat: 48.85837, lng: 2.294481, is_exact: true }, 3 { name: "UNESCO HQ", lat: 48.84956, lng: 2.306326, is_exact: false }, 4 { name: "Trocadéro", lat: 48.86278, lng: 2.28766, is_exact: false }, 5 { name: "Champ de Mars",lat: 48.85609, lng: 2.29820, is_exact: true }, 6 { name: "Bir-Hakeim", lat: 48.85032, lng: 2.28926, is_exact: false } 7 ];
JSON ist hier schlicht ein praktisches Format: lesbar, erweiterbar, und jedes Backend kann ein solches Array mit einer Zeile zurückgeben.
Die Karte selbst wird mit einem google.maps.Map-Objekt initialisiert. Zentrieren Sie sie auf den ersten Punkt des Arrays und setzen Sie den Zoom so, dass alle fünf Punkte sichtbar sind:
1 const centerMap = new google.maps.LatLng(48.856, 2.294); 2 3 const map = new google.maps.Map(document.getElementById("mapCanvas"), { 4 zoom: 14, 5 center: centerMap, 6 mapTypeId: google.maps.MapTypeId.ROADMAP, 7 mapTypeControl: true, 8 fullscreenControl: false 9 });
Benutzerdefinierte Markierungen mit unterschiedlichen Icons hinzufügen
Ohne ein eigenes Icon zeichnet jeder Aufruf von google.maps.Marker die standardmäßige rote Stecknadel. Um Punkttypen zu unterscheiden, stellen Sie in der Eigenschaft icon ein eigenes Bild bereit.
Bereiten Sie zwei Icons vor, zum Beispiel marker_exact.png (eine grüne Stecknadel für exakte Adressen) und marker_approx.png (einen blauen Kreis für ungefähre Standorte). Legen Sie die Dateien in einem images/-Ordner neben der HTML-Datei ab.
Die Logik zur Icon-Auswahl verwendet einen ternären Operator basierend auf dem Flag is_exact:
1 function plotMarker(location) { 2 const iconFile = location.is_exact ? "marker_exact.png" : "marker_approx.png"; 3 4 new google.maps.Marker({ 5 position: new google.maps.LatLng(location.lat, location.lng), 6 icon: "images/" + iconFile, 7 title: location.name, 8 map: map 9 }); 10 }
Um alle Markierungen auf einmal zu setzen, iterieren Sie durch das Array:
1 function setMarkers(locations) { 2 for (let i = 0; i < locations.length; i++) { 3 plotMarker(locations[i]); 4 } 5 }
Fertig. Fünf Punkte, zwei Icons, die Karte kennt jede Markierung. Unserer Erfahrung nach sollten Sie an dieser Stelle die Konsole öffnen und prüfen, ob alle fünf Markierungen gerendert wurden: Wenn ein Icon unter dem angegebenen Pfad nicht gefunden wurde, fällt die Markierung stillschweigend auf die Standard-Stecknadel zurück, und Sie bemerken es optisch möglicherweise gar nicht. Aber der Betrachter versteht das noch nicht. Er braucht eine Legende.
Ein paar Worte zu Icons. Die optimale Größe beträgt 40×40 px für Standarddisplays und 80×80 px für Retina (geben Sie die größere Datei im icon-Attribut an und setzen Sie scaledSize auf new google.maps.Size(40,40); das Bild wird auf Retina-Bildschirmen scharf dargestellt). Als Format kommen PNG, SVG oder WebP infrage, aber für eigene Stecknadeln bevorzugen wir SVG: Es wiegt weniger, skaliert ohne Pixelbildung und ist leicht zu bearbeiten. Falls Sie dennoch PNG verwenden, wählen Sie 24-Bit mit Alphakanal; andernfalls erscheint ein weißer Hintergrund um die Stecknadel, was auf dunklen Karten fehl am Platz wirkt.
Ein häufiger Fehler: den Pfad der Icon-Datei relativ zur HTML-Datei anzugeben statt relativ zum Server-Root. Platzieren Sie marker_exact.png im selben Ordner wie index.html und geben Sie "marker_exact.png" ohne führenden Schrägstrich an. Befinden sich die Icons in einem Unterordner wie images/, lautet der Pfad "images/marker_exact.png", genau wie im Code oben gezeigt.
Eine Legende für Markierungen erstellen
Eine Legende ist lediglich ein normales DOM-Element, das wir im Steuerelemente-Bereich der Karte platzieren. Google Maps erlaubt es, ein Steuerelement an einer der Standardpositionen zu positionieren: zum Beispiel TOP_LEFT, TOP_CENTER oder RIGHT_TOP. Für eine Legende bietet sich die obere rechte Ecke an.
Beschreiben Sie zunächst den Container in HTML und gestalten Sie ihn:
1 <div id="mapLegend"> 2 <h2>Обозначения</h2> 3 </div> 4 5 css 6 #mapLegend { 7 background: #fdfdfd; 8 color: #3c4750; 9 padding: 0 10px; 10 margin: 10px; 11 font-weight: bold; 12 opacity: 0.85; 13 border: 2px solid #000; 14 } 15 #mapLegend div { 16 height: 40px; 17 line-height: 25px; 18 font-size: 1.2em; 19 } 20 #mapLegend div img { 21 float: left; 22 margin-right: 10px; 23 } 24 #mapLegend h2 { 25 text-align: center; 26 }
Nun befüllen Sie die Legende mit Zeilen aus „Icon + Beschriftung" und übergeben sie der Karte:
1 const legend = document.getElementById("mapLegend"); 2 3 const exactDiv = document.createElement("div"); 4 exactDiv.innerHTML = '<img src="images/marker_exact.png"> Точное местоположение'; 5 legend.appendChild(exactDiv); 6 7 const approxDiv = document.createElement("div"); 8 approxDiv.innerHTML = '<img src="images/marker_approx.png"> Примерное местоположение'; 9 legend.appendChild(approxDiv); 10 11 map.controls[google.maps.ControlPosition.RIGHT_TOP].push(legend);
Die Reihenfolge ist entscheidend: Zuerst stellen Sie legend als DOM-Knoten zusammen, dann pushen Sie ihn. Wenn Sie dies umkehren, bleibt das Steuerelement leer.
Vollständiger Code: Alles zusammenfügen
Kombinieren Sie HTML, CSS und JavaScript in einer einzigen Datei. Speichern Sie sie als index.html, ersetzen Sie YOUR_API_KEY durch einen funktionierenden Schlüssel und öffnen Sie sie im Browser.

Hier die vollständige Auflistung:
1 <!doctype html> 2 <html lang="ru"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Custom Markers with Legend — Google Maps</title> 6 <style> 7 #mapCanvas { 8 width: 775px; 9 height: 500px; 10 margin: 0 auto; 11 } 12 #mapLegend { 13 background: #fdfdfd; 14 color: #3c4750; 15 padding: 0 10px; 16 margin: 10px; 17 font-weight: bold; 18 opacity: 0.85; 19 border: 2px solid #000; 20 } 21 #mapLegend div { 22 height: 40px; 23 line-height: 25px; 24 font-size: 1.2em; 25 } 26 #mapLegend div img { 27 float: left; 28 margin-right: 10px; 29 } 30 #mapLegend h2 { 31 text-align: center; 32 } 33 </style> 34 </head> 35 <body> 36 37 <div id="mapCanvas"></div> 38 39 <div id="mapLegend"> 40 <h2>Обозначения</h2> 41 </div> 42 43 <script> 44 const locations = [ 45 { name: "Eiffel Tower", lat: 48.85837, lng: 2.294481, is_exact: true }, 46 { name: "UNESCO HQ", lat: 48.84956, lng: 2.306326, is_exact: false }, 47 { name: "Trocadéro", lat: 48.86278, lng: 2.28766, is_exact: false }, 48 { name: "Champ de Mars",lat: 48.85609, lng: 2.29820, is_exact: true }, 49 { name: "Bir-Hakeim", lat: 48.85032, lng: 2.28926, is_exact: false } 50 ]; 51 52 let map; 53 54 function drawMap() { 55 const centerMap = new google.maps.LatLng(48.856, 2.294); 56 57 map = new google.maps.Map(document.getElementById("mapCanvas"), { 58 zoom: 14, 59 center: centerMap, 60 mapTypeId: google.maps.MapTypeId.ROADMAP, 61 mapTypeControl: true, 62 fullscreenControl: false 63 }); 64 65 setMarkers(locations); 66 buildLegend(); 67 } 68 69 function setMarkers(locations) { 70 for (let i = 0; i < locations.length; i++) { 71 plotMarker(locations[i]); 72 } 73 } 74 75 function plotMarker(location) { 76 const iconFile = location.is_exact ? "marker_exact.png" : "marker_approx.png"; 77 78 new google.maps.Marker({ 79 position: new google.maps.LatLng(location.lat, location.lng), 80 icon: "images/" + iconFile, 81 title: location.name, 82 map: map 83 }); 84 } 85 86 function buildLegend() { 87 const legend = document.getElementById("mapLegend"); 88 89 const exactDiv = document.createElement("div"); 90 exactDiv.innerHTML = '<img src="images/marker_exact.png"> Точное местоположение'; 91 legend.appendChild(exactDiv); 92 93 const approxDiv = document.createElement("div"); 94 approxDiv.innerHTML = '<img src="images/marker_approx.png"> Примерное местоположение'; 95 legend.appendChild(approxDiv); 96 97 map.controls[google.maps.ControlPosition.RIGHT_TOP].push(legend); 98 } 99 </script> 100 101 <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=drawMap"></script> 102 </body> 103 </html>
Ersetzen Sie YOUR_API_KEY, und die Karte wird lebendig. Ein dritter Markierungstyp bedeutet ein weiteres Icon, ein weiteres div in der Legende und eine weitere Bedingung in plotMarker. Das skaliert linear.
Wenn Sie diesen Code in Ihr Projekt übernehmen, achten Sie auf zwei Dinge. Erstens: In einer echten Anwendung werden die locations-Daten wahrscheinlich von einem Backend via fetch oder XMLHttpRequest kommen, statt fest im <script>-Tag verdrahtet zu sein. Zweitens: Wenn Sie mehr als zehn Punkte haben, verlagern Sie das Array in eine separate .json-Datei und laden Sie diese asynchron; das hält das HTML lesbar und verhindert, dass die Karte das Rendern der Seite blockiert.
Für den Produktiveinsatz mit Dutzenden von Markierungen ergänzen Sie Clustering über die Bibliothek @googlemaps/markerclusterer: Sie gruppiert nahe beieinanderliegende Punkte zu Kreisen mit Zahlen und entfaltet sie beim Zoomen zu einzelnen Stecknadeln. Installieren Sie sie via npm (npm i @googlemaps/markerclusterer) und binden Sie sie mit drei Zeilen ein: new MarkerClusterer({ map, markers }). Ohne Clustering verwandeln fünfzig Markierungen auf Stadt-Zoomstufe die Karte in ein unleserliches Durcheinander überlappender Icons.
⁉️🤔 Häufig gestellte Fragen
Kann ich anstelle von PNG SVG für Marker-Icons verwenden?
Ja, Google Maps akzeptiert jedes Format, das der Browser darstellen kann: PNG, SVG, WebP. SVG ist besonders praktisch, da es beim Zoomen nicht pixelig wird und weniger Speicher benötigt. Übergeben Sie den Pfad zur
.svg-Datei in der Eigenschafticongenauso wie bei PNG. Die Icon-Größe legen Sie über die Attributewidth/heightder SVG-Datei selbst fest: Google Maps verwendet sie als Basis und skaliert sie für die jeweilige Anzeigedichte.
Wie migriere ich von google.maps.Marker zu AdvancedMarkerElement?
Seit Februar 2024 ist
google.maps.Markerals veraltet gekennzeichnet. Die neue Klassegoogle.maps.marker.AdvancedMarkerElementverwendet HTML-Inhalt anstelle der Eigenschafticon, sodass Sie einen Button, ein Badge oder eine animierte SVG-Datei direkt in den Marker einfügen können. Binden Sie die Marker-Bibliothek ein (&libraries=markerin der API-URL) und ersetzen Sie im Konstruktoricondurchcontentmit einem DOM-Element:
1 > const marker = new google.maps.marker.AdvancedMarkerElement({ 2 > map, 3 > position: new google.maps.LatLng(location.lat, location.lng), 4 > title: location.name, 5 > content: document.createElement("img") 6 > }); 7 >
Der Inhalt kann ein beliebiges DOM-Element sein: <img>, ein <div> mit Hintergrund oder SVG. Die offizielle Migrationsanleitung behandelt jedes Ersetzungsszenario Schritt für Schritt mit Beispielen.
Wie füge ich eine Legende in der mobilen Version der Karte hinzu?
Das Steuerelement
RIGHT_TOPüberlappt die Karte auf schmalen Bildschirmen (unter 480 px). Die Lösung ist eine CSS-Media-Query: Verschieben Sie die Legende beimax-width: 480pxnachBOTTOM_CENTERoder reduzieren Sie Schriftgröße und Innenabstand um die Hälfte. Eine Alternative ist, die Legende außerhalb der Karte als statischen Block zu platzieren und den Zustand per JavaScript zu synchronisieren. FürBOTTOM_CENTERändern Sie einfach die Position innerhalb vonbuildLegend().
Wie viele Marker verkraftet die Karte ohne Performance-Probleme?
Bis zu 100 Marker auf dem Bildschirm verursachen keine spürbare Verzögerung, selbst auf Mittelklasse-Smartphones. Ab 100 bis 500 Markern bemerkt man Verzögerungen beim Zoomen und Verschieben. Für 500 und mehr aktivieren Sie Clustering; Google stellt die fertige Bibliothek
@googlemaps/markerclustererbereit, die nahe beieinanderliegende Marker zu nummerierten Kreisen gruppiert. In der Praxis: 50 Marker mit 2 KB großen PNG-Icons bedeuten 100 KB Download und sofortiges Rendering. 500 Marker ohne Clustering bedeuten, dass die Karte pro Zoom-Frame etwa 500drawImage()-Aufrufe ausführt, was spürbar wird.
Was zu tun ist, wenn Marker nicht angezeigt werden
Prüfen Sie zuerst die Browser-Konsole. Typische Fehler: MissingKeyMapError (API-Schlüssel nicht angegeben), RefererNotAllowedMapError (Domain nicht in der Zulassungsliste des Schlüssels), Cannot read property 'maps' of undefined (API-Skript wurde nicht geladen; prüfen Sie die URL und den callback). Öffnen Sie die DevTools auf dem Tab „Konsole" und laden Sie die Seite neu; die rote Fehlerzeile zeigt sofort die Ursache.
Stellen Sie zweitens sicher, dass der Container #mapCanvas im DOM existiert, wenn drawMap() aufgerufen wird. Befindet sich Ihr Skript im <head> ohne defer, ist das Element noch nicht gerendert und die Karte scheitert stillschweigend. Die Attribute [async defer](/orig_post/luchshij-sposob-zagruzit-vneshnij-javascript) am <script>-Tag lösen das Problem, aber die beste Praxis ist, das <script>-Tag am Ende von <body> zu platzieren, nach allen DOM-Elementen.
Prüfen Sie drittens die Icon-Pfade. Befindet sich marker_exact.png nicht relativ zur HTML-Datei in images/, liefert der Browser einen 404 für das Bild und der Marker wird als standardmäßige rote Stecknadel dargestellt (oder gar nicht, je nach API-Version). Tipp: Überprüfen Sie Pfade stets über den Tab „Netzwerk" in den DevTools, indem Sie nach dem Typ „Img" filtern; fehlerhafte Icons werden sofort rot hervorgehoben.
Am wichtigsten: Testen Sie immer mit einem echten Schlüssel. Ohne Schlüssel oder mit einem ungültigen Schlüssel wird die Karte abgedunkelt und mit dem Wasserzeichen „Nur für Entwicklungszwecke" versehen, und einige API-Methoden geben leere Antworten zurück. Wir hatten einen Fall, bei dem die Karte auf der Staging-Umgebung einwandfrei funktionierte, die Legende aber in der Produktion nicht angezeigt wurde: Es stellte sich heraus, dass der Produktionsschlüssel per IP eingeschränkt war und die API die Steuerelemente stillschweigend verweigerte. Prüfen Sie die Schlüsseleinschränkungen in der Cloud Console vor dem Deployment.
Wir haben den vollständigen Zyklus behandelt: von der Beschaffung eines Schlüssels bis zu einer live geschalteten Karte mit Legende. Wir haben den obigen Code mit Google Maps API v3.56 (aktuell Stand Juni 2026) getestet; alle fünf Marker mit benutzerdefinierten Icons wurden korrekt dargestellt und die Legende in RIGHT_TOP überlappte die Zoom-Steuerelemente nicht.
Wenn Sie weitergehen, behalten Sie drei Dinge im Hinterkopf. Erstens: Laden Sie Icons immer in der Größe, in der sie auf der Karte erscheinen, da die nachträgliche Größenänderung durch den Browser beim Zoomen Frames kostet. Zweitens: Für Karten mit Dutzenden von Markern ist Clustering zwingend erforderlich, andernfalls werden sich mobile Nutzer mit Verzögerungen bedanken. Drittens: Schränken Sie den API-Schlüssel von Tag eins an per HTTP-Referrer ein, selbst in Entwicklungsumgebungen; ein geleakter Schlüssel ohne Einschränkungen ist ein direkter Weg zu fremdem Traffic auf Ihrem Abrechnungskonto.
Sollte die Aufgabe komplexer werden (Clustering, Info-Fenster bei Klick, Marker-Filterung nach Kategorien), lassen Sie uns in den Kommentaren wissen, welches Szenario wir als Nächstes behandeln sollen.



