Skip to content

Add Custom Icons with Markers

Use the Marker API with a custom HTML element to display any icon — emoji, SVG, image, or styled div — as a map marker.

Default vs Custom Marker

javascript
// Default marker (blue pin)
new mapmetricsgl.Marker()
  .setLngLat([lng, lat])
  .addTo(map);

// Custom HTML marker
const el = document.createElement('div');
el.innerHTML = '⭐';
el.style.fontSize = '32px';
el.style.cursor = 'pointer';

new mapmetricsgl.Marker({ element: el })
  .setLngLat([lng, lat])
  .addTo(map);

Create a Styled Div Marker

javascript
function createCustomMarker(emoji, color) {
  const el = document.createElement('div');
  el.style.cssText = `
    width: 44px;
    height: 44px;
    background: ${color};
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    border: 2px solid #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    cursor: pointer;
  `;
  el.textContent = emoji;
  return el;
}

const el = createCustomMarker('🏪', '#3b82f6');
new mapmetricsgl.Marker({ element: el })
  .setLngLat([-74, 40.7])
  .addTo(map);

Use an Image as the Marker

javascript
const el = document.createElement('img');
el.src = 'https://example.com/icon.png';
el.style.width = '40px';
el.style.height = '40px';

new mapmetricsgl.Marker({ element: el })
  .setLngLat([lng, lat])
  .addTo(map);

Marker with Popup

javascript
const popup = new mapmetricsgl.Popup({ offset: 25 })
  .setHTML('<strong>My Location</strong><p>Description here</p>');

new mapmetricsgl.Marker({ element: el })
  .setLngLat([lng, lat])
  .setPopup(popup)
  .addTo(map);

Marker Options

javascript
new mapmetricsgl.Marker({
  element: el,       // custom HTML element
  anchor: 'center',  // 'center', 'top', 'bottom', 'left', 'right', 'top-left', etc.
  offset: [0, -20],  // [x, y] pixel offset
  draggable: true,   // allow the user to drag the marker
})

Complete Example

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
    <script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
    <style>
      #map { height: 500px; width: 100%; }
      .custom-marker {
        width: 44px; height: 44px;
        border-radius: 50%;
        display: flex; align-items: center; justify-content: center;
        font-size: 22px;
        border: 2px solid #fff;
        box-shadow: 0 2px 6px rgba(0,0,0,0.3);
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      const map = new mapmetricsgl.Map({
        container: 'map',
        style: '<StyleFile_URL_with_Token>',
        center: [10, 30],
        zoom: 1.5
      });

      map.on('load', () => {
        const places = [
          { coords: [-74, 40.7], emoji: '🗽', color: '#3b82f6', name: 'New York' },
          { coords: [2.35, 48.85], emoji: '🗼', color: '#ef4444', name: 'Paris' },
          { coords: [139.7, 35.7], emoji: '⛩️', color: '#f59e0b', name: 'Tokyo' },
        ];

        places.forEach(({ coords, emoji, color, name }) => {
          const el = document.createElement('div');
          el.className = 'custom-marker';
          el.style.background = color;
          el.textContent = emoji;

          new mapmetricsgl.Marker({ element: el })
            .setLngLat(coords)
            .setPopup(new mapmetricsgl.Popup({ offset: 25 }).setHTML(`<strong>${name}</strong>`))
            .addTo(map);
        });
      });
    </script>
  </body>
</html>
jsx
import React, { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const places = [
  { coords: [-74, 40.7], emoji: '🗽', color: '#3b82f6', name: 'New York' },
  { coords: [2.35, 48.85], emoji: '🗼', color: '#ef4444', name: 'Paris' },
  { coords: [139.7, 35.7], emoji: '⛩️', color: '#f59e0b', name: 'Tokyo' },
];

const AddCustomIconsMarkers = () => {
  const mapContainer = useRef(null);
  const map = useRef(null);
  const markers = useRef([]);

  useEffect(() => {
    if (map.current) return;
    map.current = new mapmetricsgl.Map({
      container: mapContainer.current,
      style: '<StyleFile_URL_with_Token>',
      center: [10, 30],
      zoom: 1.5
    });

    map.current.on('load', () => {
      places.forEach(({ coords, emoji, color, name }) => {
        const el = document.createElement('div');
        Object.assign(el.style, {
          width: '44px', height: '44px',
          background: color, borderRadius: '50%',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: '22px', border: '2px solid #fff',
          boxShadow: '0 2px 6px rgba(0,0,0,0.3)', cursor: 'pointer'
        });
        el.textContent = emoji;

        const marker = new mapmetricsgl.Marker({ element: el })
          .setLngLat(coords)
          .setPopup(new mapmetricsgl.Popup({ offset: 25 }).setHTML(`<strong>${name}</strong>`))
          .addTo(map.current);

        markers.current.push(marker);
      });
    });

    return () => {
      markers.current.forEach(m => m.remove());
      map.current?.remove(); map.current = null;
    };
  }, []);

  return <div ref={mapContainer} style={{ height: '500px', width: '100%' }} />;
};

export default AddCustomIconsMarkers;

For more information, visit the MapMetrics GitHub repository.