# Map

[component-header:sl-map]

Map is a visual overview of geographical data.

```html preview
<sl-map id="map-el" style="height:400px;" access-token="pk.eyJ1IjoibWljaGFlbGtyb2ciLCJhIjoiY2szdHp0Y3RzMDd0NjNrcTh2ZXloZ2JqMyJ9.XYFkQDw6jLJk1iBmNe7tGA"></sl-map>

<script>
  const data = {"geometry":{"coordinates":[[9.935098,57.042438],[9.935098,57.042438],[9.935362,57.04244],[9.93603,57.042444],[9.937,57.04245],[9.938,57.042457],[9.940376,57.042467],[9.940638,57.042326],[9.940722,57.042372],[9.941076,57.042563],[9.942057,57.04305],[9.942932,57.043439],[9.942994,57.043464],[9.943114,57.043523],[9.944265,57.043936],[9.945416,57.044341],[9.946489,57.044712],[9.946856,57.044813],[9.947025,57.044873],[9.947089,57.044917],[9.947128,57.044944],[9.947174,57.044961],[9.947237,57.044967],[9.947378,57.044931],[9.947627,57.044865],[9.947766,57.044819],[9.947866,57.044777],[9.947957,57.04473],[9.94807,57.044665],[9.948088,57.044653],[9.948214,57.04457],[9.94834,57.044487],[9.948473,57.044399],[9.949056,57.044116],[9.94939,57.043898],[9.949565,57.043753],[9.950287,57.042773],[9.95039,57.042632],[9.950635,57.042294],[9.950721,57.042175],[9.951225,57.041477],[9.951562,57.041038],[9.951593,57.040998],[9.951763,57.040774],[9.951823,57.040694],[9.952019,57.040408],[9.952128,57.040218],[9.952208,57.039983],[9.952262,57.039749],[9.952349,57.039373],[9.952363,57.039228],[9.952414,57.039032],[9.952479,57.038863],[9.952492,57.038812],[9.952629,57.038317],[9.952771,57.037783],[9.95284,57.037533],[9.952912,57.037288],[9.952952,57.037119],[9.953028,57.036856],[9.953096,57.036621],[9.953439,57.035747],[9.953478,57.035653],[9.953543,57.0355],[9.95365,57.035248],[9.953734,57.035053],[9.953982,57.034468],[9.954121,57.034167],[9.954143,57.034007],[9.954156,57.033974],[9.954178,57.033921],[9.954184,57.033907],[9.954223,57.033814],[9.954072,57.033794],[9.953759,57.033746],[9.953257,57.033612],[9.953077,57.033585],[9.952971,57.033574],[9.952802,57.033556],[9.952602,57.033535],[9.951906,57.033443],[9.951536,57.0334],[9.95113,57.033362],[9.950499,57.033316],[9.949352,57.03324],[9.944419,57.032931],[9.94382,57.032888],[9.943181,57.032854],[9.943089,57.032848],[9.942921,57.032817],[9.942852,57.032785],[9.9428,57.032747],[9.942776,57.032698],[9.942818,57.032653],[9.942845,57.032623],[9.943078,57.032342],[9.943207,57.032171],[9.943358,57.031955],[9.943591,57.031565],[9.943752,57.031495],[9.943906,57.03119],[9.944081,57.030735],[9.944218,57.030344],[9.944319,57.029946],[9.944377,57.029673],[9.944405,57.029356],[9.943679,57.029341],[9.943588,57.029342],[9.943289,57.029353],[9.94291,57.029379],[9.942547,57.029443],[9.942428,57.029464],[9.942928,57.030032],[9.942428,57.029464],[9.942547,57.029443],[9.94291,57.029379],[9.943289,57.029353],[9.943588,57.029342],[9.943679,57.029341],[9.944405,57.029356],[9.944377,57.029673],[9.944319,57.029946],[9.944218,57.030344],[9.944081,57.030735],[9.943906,57.03119],[9.943752,57.031495],[9.943756,57.031578],[9.943537,57.031976],[9.94337,57.032209],[9.943061,57.032642],[9.943042,57.032665],[9.943023,57.032689],[9.942983,57.032738],[9.942921,57.032817],[9.942552,57.033201],[9.942374,57.033371],[9.941865,57.033845],[9.941257,57.034248],[9.940255,57.034896],[9.94018,57.034941],[9.939605,57.035292],[9.939314,57.035513],[9.939239,57.035559],[9.939091,57.03566],[9.938958,57.035747],[9.937636,57.036602],[9.93707,57.03699],[9.93667,57.037271],[9.93641,57.037533],[9.936109,57.037865],[9.93602,57.037963],[9.936191,57.037984],[9.936891,57.038097],[9.937358,57.03818],[9.937876,57.038279],[9.938277,57.038363],[9.93873,57.038464],[9.939339,57.038613],[9.939935,57.03877],[9.9401,57.038817],[9.94059,57.038956],[9.940682,57.038985],[9.940831,57.039033],[9.940745,57.039124],[9.940735,57.039213],[9.940515,57.039407],[9.940436,57.03946],[9.939974,57.039942],[9.939873,57.040038],[9.939855,57.040056],[9.939697,57.040206],[9.939521,57.040349],[9.939458,57.040453],[9.939105,57.040691],[9.938791,57.040876],[9.938608,57.040936],[9.938481,57.041014],[9.938258,57.041182],[9.938109,57.041392],[9.938035,57.041597],[9.938018,57.041737],[9.938001,57.042363],[9.938,57.042457],[9.937992,57.042563],[9.936999,57.042559],[9.935656,57.042555],[9.935358,57.042554],[9.935096,57.042553],[9.935098,57.042438]],"type":"LineString"},"legs":[{"steps":[],"distance":3477.7,"duration":375.6,"summary":"","weight":392.4},{"steps":[],"distance":2249.7,"duration":288.4,"summary":"","weight":305.2}],"distance":5727.4,"duration":664,"weight_name":"routability","weight":697.6, "type": "Feature"};
  const map = document.getElementById('map-el');
  map.addSource('routeid', {type:'geojson', data});

  map.addLayer({
    id: 'routeid-border',
    type: 'line',
    source: 'routeid',
    layout: {
      'line-join': 'round',
      'line-cap': 'round'
    },
    paint: {
      'line-color': '#2563eb',
      'line-width': 6
    }
  });

  map.addLayer({
    id: 'routeid',
    type: 'line',
    source: 'routeid',
    layout: {
      'line-join': 'round',
      'line-cap': 'round'
    },
    paint: {
      'line-color': '#3b82f6',
      'line-width': 4
    }
  });
</script> 
```

## Cluster

```html preview
<sl-map id="map-el2" lng="11.33733945527472" lat="55.40938384194578" style="height:400px;" access-token="pk.eyJ1IjoibWljaGFlbGtyb2ciLCJhIjoiY2szdHp0Y3RzMDd0NjNrcTh2ZXloZ2JqMyJ9.XYFkQDw6jLJk1iBmNe7tGA"></sl-map>

<script>
  const features = [
    { "type": "Feature", "properties": { "id": "c-1", "name": 'Karl Petersen' }, "geometry": { "type": "Point", "coordinates": [11.33033945527472, 55.40938384194578] } },
    { "type": "Feature", "properties": { "id": "c-2", "name": 'Jørgen Larsen' }, "geometry": { "type": "Point", "coordinates": [11.33733245527472, 55.40978384194578] } },
    { "type": "Feature", "properties": { "id": "c-3", "name": 'Hanne Johansen' }, "geometry": { "type": "Point", "coordinates": [11.34033945527472, 55.50938384194578] } },
    { "type": "Feature", "properties": { "id": "c-4", "name": 'Peter Minde' }, "geometry": { "type": "Point", "coordinates": [11.34733245527472, 55.50978384194578] } }
  ];
  const geojson = {
    type: "FeatureCollection",
    features
  };
  const map = document.getElementById('map-el2');

  map.addSource('locations', {
    type:'geojson', 
    data:geojson, 
    cluster: true,
    clusterMaxZoom: 14, 
    clusterRadius: 50
  });

  // objects for caching and keeping track of HTML marker objects (for performance)
  const markers = {};
  let markersOnScreen = {};

  function createBubble(text) {
    const bubble = document.createElement('sl-bubble');
    bubble.style.transition = 'font-size var(--sl-transition-fast)';
    bubble.style.filter = 'drop-shadow(0px 1px 2px #6b7280)';
    bubble.innerHTML = text;
    return bubble;
  }

  async function updateMarkers() {
    const newMarkers = {};
    const innerMap = await map.getInnerMap();
    const features = innerMap.querySourceFeatures('locations');
    
    
    // for every cluster on the screen, create an HTML marker for it (if we didn't yet),
    // and add it to the map if it's not there already
    for (const feature of features) {
      const coords = feature.geometry.coordinates;
      const props = feature.properties;
      let id;
      let marker;

      if (!props.cluster) {
        id = props.id;
        const name = props.name.substring(0,2);
        
        marker = markers[id];
        if (!marker) {
          /**
           * this.map?.addMarker(a.id, a.location[0], a.location[1], { element: bubble, anchor: 'bottom' });
           * */
          const el = createBubble(name);
          marker = markers[id] = { element: el, anchor: 'bottom' };
        }
      } else {
        const pointCount = props.point_count;
        const text = pointCount < 10 ? `${pointCount}` : '9+';
        id = props.cluster_id;
        
        marker = markers[id];
        if (!marker) {
          /**
           * this.map?.addMarker(a.id, a.location[0], a.location[1], { element: bubble, anchor: 'bottom' });
           * */
          const el = createBubble(text);
          marker = markers[id] = { element: el, anchor: 'bottom' };
        }
      }
      newMarkers[id] = marker;
      
      if (!markersOnScreen[id]) map.addMarker(id, coords[0], coords[1], marker);
    }

    // for every marker we've added previously, remove those that are no longer visible
    for (const id in markersOnScreen) {
      if (!newMarkers[id]) map.removeMarker(id);
    }
    markersOnScreen = newMarkers;
  }

  map.getInnerMap().then(im => {
      im.on('render', () => {
        const source = im.getSource('locations');
        if(source == null) return;
        updateMarkers();
      });
  });


/** Required to force the map to paint markers */
map.addLayer({
'id': 'dummy_circle',
'type': 'circle',
'source': 'locations',
'paint': {
'circle-opacity': 0.0
}
});/*

  map.addLayer({
    id: 'clusters',
    type: 'circle',
    source: 'locations',
    filter: ['has', 'point_count'],
    paint: {
      // Use step expressions (https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)
      // with three steps to implement three types of circles:
      //   * Blue, 20px circles when point count is less than 100
      //   * Yellow, 30px circles when point count is between 100 and 750
      //   * Pink, 40px circles when point count is greater than or equal to 750
      'circle-color': [
        'step',
        ['get', 'point_count'],
        '#51bbd6',
        100,
        '#f1f075',
        750,
        '#f28cb1'
        ],
        'circle-radius': [
        'step',
        ['get', 'point_count'],
        20,
        100,
        30,
        750,
        40
      ]
    }
  });

  map.addLayer({
    id: 'cluster-count',
    type: 'symbol',
    source: 'locations',
    filter: ['has', 'point_count'],
    layout: {
    'text-field': ['get', 'point_count_abbreviated'],
    'text-size': 12
    }
  });

  map.addLayer({
    id: 'unclustered-point',
    type: 'circle',
    source: 'locations',
    filter: ['!', ['has', 'point_count']],
    paint: {
    'circle-color': '#11b4da',
    'circle-radius': 4,
    'circle-stroke-width': 1,
    'circle-stroke-color': '#fff'
    }
  });*/


</script>
```
[component-metadata:sl-map]