
📍 Slik legger du til flere tilpassede markører med en tegnforklaring i Google Maps
Markører er den vanligste måten å angi et punkt på et kart. Den standard røde Google Maps-nålen er gjenkjennelig, men når du har fem punkter av ulike typer, mister brukerne oversikten: hvilken er en eksakt adresse og hvilken er et omtrentlig landemerke?
Dette skjer hele tiden: en butikkatalog delt inn i «egeneide» og «partner»-lokasjoner, et leveringskart med soner, et logistikkpanel med lastetyper. Overalt hvor du har mer enn tre punkter med ulik betydning, oppstår det kaos uten tilpassede ikoner og en tegnforklaring.
Løsningen er tilpassede markørikoner og en tegnforklaring som forklarer hvert symbol. På 20 minutter bygger du et kart med flere markørtyper, og brukerne vil forstå hva som er hva ved første øyekast. I praksis har vi sett gang på gang at et par ulike nåler og en tegnforklaringsblokk i hjørnet sparer brukerne for minutter med tolking og sparer supportteamene for dusinvis av «hva betyr den blå sirkelen?»-spørsmål.
Nedenfor følger en trinnvis gjennomgang med vanlig JavaScript, uten rammeverk. Vi bruker koordinater rundt Eiffeltårnet, et praktisk landemerke med gjenkjennelig geometri. Koden er bevisst minimal, og hver metode forklares linje for linje slik at du kan tilpasse den til din oppgave uten å lese hele dokumentasjonen.
Stoffet går fra enkelt til komplekst: først skaffer du en API-nøkkel og viser et grunnleggende kart, deretter legger du til markører med ulike ikoner, bygger en tegnforklaring, og til slutt har du en fungerende HTML-fil som kjører uten videre oppsett. Alle eksemplene er testet i Google Chrome 120+, Firefox 121+ og Safari 17+.
💡 Rask oversikt:
- Skaff en Google Maps API-nøkkel og inkluder biblioteket
- Forbered en liste med punkter i JSON: navn, koordinater, type (eksakt/omtrentlig)
- Tildel hver type sitt eget ikon via
icon-egenskapen - Bygg tegnforklaringen som et HTML-element og fest det til kartet via
map.controls - Resultat: ett kart, to visuelle markørtyper, tegnforklaring i øvre høyre hjørne
Skaffe en Google Maps API-nøkkel
Å jobbe med JavaScript Maps API krever en nøkkel. Hvis du ikke har en, opprett den i Google Cloud Console.
Raske steg: gå til Console, opprett et prosjekt (eller velg et eksisterende), aktiver Maps JavaScript API, generer en nøkkel. For lokal utvikling er det tilstrekkelig å begrense nøkkelen med HTTP-referrer; for produksjon legger du til domenet ditt i tillatelseslisten. I reelle prosjekter oppretter vi alltid en separat nøkkel for hver applikasjon: det er enklere å spore kvoter i Cloud Console og presist tilbakekalle tilgang hvis en nøkkel lekker.
Å inkludere biblioteket krever én linje i <script>:
1 <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=drawMap"></script>
callback-attributtet spesifiserer hvilken funksjon som kjøres etter at API-et er lastet inn. Den skriver vi straks.

Viktig: siden februar 2024 er klassen
google.maps.Markeroffisielt merket som utdatert. Den er erstattet avgoogle.maps.marker.AdvancedMarkerElement, som gir bedre ytelse og støtter tilpasset HTML. Koden nedenfor bruker den klassiskeMarker(den fungerer fortsatt og er enklere å begynne med), og FAQ-delen inneholder en lenke til migreringsguiden for å bytte til AdvancedMarkerElement.
Initialisere kartet og forberede data
Først en beholder for kartet og en liste med koordinater. Bruk hvilke koordinater du vil; her har vi fem punkter rundt Eiffeltårnet i Paris, tre eksakte og to omtrentlige.
1 <div id="mapCanvas"></div>
Vi pakker dataene i en liste med objekter. Feltet is_exact skiller markørene i to typer: de som angir en eksakt adresse og de som angir et generelt område.
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 her er rett og slett et praktisk format: lesbart, utvidbart, og enhver backend kan returnere en slik liste på én linje.
Selve kartet initialiseres med et google.maps.Map-objekt. Sentrer det på det første punktet i listen, sett zoom slik at alle fem får plass:
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 });
Legge til egendefinerte markører med ulike ikoner
Uten et egendefinert ikon tegner hvert google.maps.Marker-kall den standard røde nålen. For å skille punkttyper, oppgir du ditt eget bilde i icon-egenskapen.
Forbered to ikoner, for eksempel marker_exact.png (en grønn nål for eksakte adresser) og marker_approx.png (en blå sirkel for omtrentlige posisjoner). Plasser filene i en images/-mappe sammen med HTML-filen.
Ikonvalglogikken bruker en ternær operator basert på is_exact-flagget:
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 }
For å plassere alle markørene samtidig, itererer du gjennom listen:
1 function setMarkers(locations) { 2 for (let i = 0; i < locations.length; i++) { 3 plotMarker(locations[i]); 4 } 5 }
Ferdig. Fem punkter, to ikoner, kartet kjenner til hver markør. Etter vår erfaring bør du på dette stadiet åpne konsollen og bekrefte at alle fem markørene ble tegnet: hvis et ikon ikke ble funnet på den angitte banen, faller markøren stille tilbake til standardnålen, og du legger kanskje ikke engang merke til det visuelt. Men betrakteren forstår det ikke ennå. De trenger en tegnforklaring.
Noen ord om ikoner. Optimal størrelse er 40×40 piksler for standard skjermer og 80×80 piksler for Retina (angi den større filen i icon-attributtet og sett scaledSize til new google.maps.Size(40,40); bildet blir skarpt på retina-skjermer). Formatet kan være PNG/SVG/WebP, men for egendefinerte nåler foretrekker vi SVG: det veier mindre, skalerer uten pikselering og er enkelt å redigere. Hvis du likevel bruker PNG, velg 24-bit med alfakanal; ellers dukker det opp en hvit bakgrunn rundt nålen, noe som ser malplassert ut på mørke kart.
En vanlig feil: å angi ikonfilbanen relativt til HTML-filen i stedet for relativt til serverroten. Plasser marker_exact.png i samme mappe som index.html og angi "marker_exact.png" uten innledende skråstrek. Hvis ikonene ligger i en undermappe som images/, blir banen "images/marker_exact.png", nøyaktig som vist i koden over.
Lage en tegnforklaring for markører
En tegnforklaring er bare et vanlig DOM-element som vi plasserer i kartets kontrollsone. Google Maps lar deg plassere en kontroll i én av standardposisjonene: for eksempel TOP_LEFT, TOP_CENTER eller RIGHT_TOP. For en tegnforklaring gir øverste høyre hjørne mening.
Først beskriver du beholderen i HTML og styler den:
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 }
Nå fyller du tegnforklaringen med «ikon + etikett»-rader og gir den til kartet:
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);
Rekkefølgen er viktig: sett først sammen legend som en DOM-node, og skyv den deretter inn. Hvis du reverserer dette, forblir kontrollen tom.
Fullstendig kode: setter alt sammen
Kombiner HTML, CSS og JavaScript i én enkelt fil. Lagre den som index.html, erstatt YOUR_API_KEY med en fungerende nøkkel, og åpne den i en nettleser.

Her er den endelige oppføringen:
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>
Erstatt YOUR_API_KEY, så våkner kartet til live. Å legge til en tredje markørtype betyr et nytt ikon, en ny div i tegnforklaringen og en ny betingelse i plotMarker. Det skalerer lineært.
Når du overfører denne koden til prosjektet ditt, vær oppmerksom på to ting. For det første: i en ekte applikasjon vil locations-dataene sannsynligvis komme fra en backend via fetch eller XMLHttpRequest i stedet for å være hardkodet i <script>. For det andre: hvis du har mer enn ti punkter, flytt listen til en separat .json-fil og last den asynkront; dette holder HTML-en lesbar og forhindrer at kartet blokkerer sidegjengivelsen.
For produksjon med dusinvis av markører, legg til clustering via biblioteket @googlemaps/markerclusterer: det grupperer nærliggende punkter i sirkler med tall, og utvider dem deretter til individuelle nåler når man zoomer. Installer via npm (npm i @googlemaps/markerclusterer) og koble til med tre linjer: new MarkerClusterer({ map, markers }). Uten clustering blir femti markører på byzoom-nivå et uleselig rot av overlappende ikoner.
⁉️🤔 Ofte stilte spørsmål
Kan jeg bruke SVG i stedet for PNG for markørikoner?
Ja, Google Maps godtar alle formater nettleseren kan gjengi: PNG, SVG, WebP. SVG er spesielt praktisk siden det ikke pikselerer ved zooming og veier mindre. Send inn banen til
.svg-filen iicon-egenskapen nøyaktig slik du ville gjort for PNG. Angi ikonstørrelse viawidth-/height-attributtene i selve SVG-filen: Google Maps vil bruke dem som utgangspunkt og skalere for skjermtettheter.
Hvordan migrerer jeg fra google.maps.Marker til AdvancedMarkerElement?
Siden februar 2024 er
google.maps.Markermerket som utdatert. Den nye klassengoogle.maps.marker.AdvancedMarkerElementbruker HTML-innhold i stedet foricon-egenskapen, så du kan sette inn en knapp, et merke eller animert SVG direkte i markøren. Inkluder markørbiblioteket (&libraries=markeri API-URL-en), og bytt uticonmedcontentsom inneholder et DOM-element i konstruktøren:
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 >
Innholdet kan være et hvilket som helst DOM-element: <img>, en <div> med bakgrunn eller SVG. Den offisielle migreringsguiden dekker hvert erstatningsscenario steg for steg med eksempler.
Hvordan legger jeg til en tegnforklaring i mobilversjonen av kartet?
RIGHT_TOP-kontrollen overlapper kartet på smale skjermer (under 480 px). Løsningen er en CSS media query: formax-width: 480px, flytt tegnforklaringen tilBOTTOM_CENTEReller reduser skriftstørrelse og padding med halvparten. Et alternativ er å plassere tegnforklaringen utenfor kartet som en statisk blokk og synkronisere tilstand via JavaScript. ForBOTTOM_CENTERendrer du ganske enkelt posisjonen inne ibuildLegend().
Hvor mange markører kan kartet håndtere uten ytelsesproblemer?
Opptil 100 markører på skjermen gir ingen merkbar treghet, selv på mellomklasse smarttelefoner. Fra 100 til 500 begynner du å se forsinkelser ved zooming og panorering. For 500+ aktiver clustering; Google tilbyr det ferdige biblioteket
@googlemaps/markerclusterersom grupperer nærliggende markører i nummererte sirkler. I praksis: 50 markører med 2 KB PNG-ikoner betyr 100 KB nedlastinger og umiddelbar gjengivelse. 500 markører uten clustering betyr at kartet gjør ~500drawImage()-kall per zoom-ramme, noe som blir merkbart.
Hva du skal gjøre hvis markører ikke vises
Først, sjekk nettleserkonsollen. Typiske feil: MissingKeyMapError (API-nøkkel ikke oppgitt), RefererNotAllowedMapError (domene ikke i nøkkelens tillatelsesliste), Cannot read property 'maps' of undefined (API-skriptet ble ikke lastet; sjekk URL-en og callback). Åpne DevTools på Console-fanen og oppdater siden; den røde feillinjen vil umiddelbart vise rotårsaken.
For det andre, sørg for at #mapCanvas-beholderen finnes i DOM-en når drawMap() kalles. Hvis skriptet ditt ligger i <head> uten defer, har elementet ikke blitt rendret ennå og kartet feiler lydløst. [async defer](/orig_post/luchshij-sposob-zagruzit-vneshnij-javascript)-attributtene på <script>-taggen løser dette, men beste praksis er å plassere <script>-taggen på slutten av <body>, etter alle DOM-elementer.
For det tredje, sjekk ikonbaner. Hvis marker_exact.png ikke ligger i images/ relativt til HTML-filen, returnerer nettleseren en 404 for bildet og markøren gjengis som standard rød nål (eller gjengis ikke i det hele tatt, avhengig av API-versjon). Tips: verifiser alltid baner via Network-fanen i DevTools ved å filtrere på Img-type; ødelagte ikoner vil bli uthevet i rødt umiddelbart.
Viktigst av alt: test alltid med en ekte nøkkel. Uten nøkkel eller med en ugyldig nøkkel blir kartet mørklagt med et vannmerke «Kun for utviklingsformål», og enkelte API-metoder returnerer tomme svar. Vi hadde et tilfelle der kartet fungerte perfekt i staging, men tegnforklaringen ikke vistes i produksjon: det viste seg at produksjonsnøkkelen var begrenset av IP, og API-et nektet lydløst kontroller. Sjekk nøkkelbegrensninger i Cloud Console før deploy.
Vi dekket hele syklusen: fra å skaffe en nøkkel til et levende kart med tegnforklaring. Vi testet koden over på Google Maps API v3.56 (gjeldende per juni 2026); alle fem markører med egendefinerte ikoner ble gjengitt korrekt, og tegnforklaringen i RIGHT_TOP overlappet ikke zoomkontrollene.
Hvis du går videre, ha tre ting i bakhodet. For det første: last alltid ikoner i den størrelsen de vil vises på kartet, siden nettleserens skalering i farten koster bilder under zooming. For det andre: for kart med dusinvis av markører er clustering obligatorisk, ellers vil mobilklienter takke deg med treghet. For det tredje: hold API-nøkkelen under begrenset HTTP-referrer fra dag én, selv i utviklingsmiljøer; en lekket nøkkel uten begrensninger er en direkte vei til andres trafikk på din faktureringskonto.
Hvis oppgaven blir mer kompleks (clustering, infovinduer ved klikk, markørfiltrering etter kategorier), gi oss beskjed i kommentarene om hvilket scenario vi skal dekke neste gang.



