16 Paź 2019

Jak dodać kolorowe markery w postaci svg oraz legendę do map z leaflet

Założenia naszego przykładu to:
- markery w różnych kolorach
- kolory markerów opisane w legendzie po prawej stornie na dole

Markery

Aby markery miały różne kolory najlepiej wykonać je w svg a kolory uzyskujemy przez dodanie parametru fill="nasz-color". Oczywiście jest wiele innych możliwości, jak wykorzystanie png, czy nawet font awesome i kolorowanie odpowiednie i wiele innych.

Zaczynamy od stworzenia html, do którego w sekcji head dodajemy style oraz js z cdn dotyczące leaflet. Html posiada div z id map, do którego będziemy "pakować" całą mapę 😉

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css">
  <link rel="stylesheet" href="style.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.js"></script>
</head>

<body>
  <div id="map"></div>
  <script src="script.js"></script>
</body>

</html>

Następnie w pliku script.js dodajemy poniższy kod który odpowiada za wyświetlenie mapy a dokładnie mapy z Warszawą.

const map = L.map('map').setView([52.237049, 21.017532], 13)

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map)

Style leaflet

Dobra mapa jest skończona to teraz tworzymy i uzupełniamy style.css

html,
body {
  height: 100%;
  margin: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
}

#map {
  width: 100%;
  height: 100%;
}

.legend {
  background: #fff;
  padding: 8px;
  border-radius: 5px;
}

.legend .row {
  display: flex;
  line-height: 30px;
}

.legend i {
  display: block;
  width: 30px;
  height: 30px;
  margin-right: 5px;
}

Raczej nie trzeba tłumaczyć co w tym css się dzieje, sądzę że jest wszystko jasne.

Legenda leaflet

W związku z tym że w css dodałem już style związane z legendą to i czas najwyższy dodać js do wyświetlania legendy.

// LEGENDS

const legend = L.control({ position: 'bottomright' })

const div = L.DomUtil.create('div', 'legend')
const color = ['F7FADA', 'B6E1C9', '72C7D4', '64A1CC', '5F6CB3']
const label = ['2-12.5', '12.6-16.8', '16.9-20.9', '21-25.9', '26-plus']
const rows = []

legend.onAdd = function (map) {
  color.map((item, index) => {
    rows.push(`
        <div class="row">
          <i style="background: #${item}"></i>${label[index]}
        </div>  
    `)
  })
  div.innerHTML = rows.join('')
  return div
}

legend.addTo(map)

Małe wytłumaczenie. Najpierw ustawiamy gdzie nasza legenda ma się pojawić. Ja wybrałem bottomright - prawy dolny róg. Oczywiście można wybrać inne położenia, a dokładnie jest ich cztery. Oprócz bottomright jest bottomleft, topleft oraz topright.

Drugą rzeczą jest stworzenie div który dodamy do legendy na zdarzenie onAdd.
Tablica color jak sama nazwa wskazuje składa się z naszych kolorów, label zaś jest opisem tych kolorów a dokładnie tablicą zakresów. Rows jest pustą tablicą do której za pomocą map będziemy dodawać poszczególne kolory oraz opis (label).

Na końcu do diva o klasie legend dodajemy wszystkie elementy.

Teraz przechodzimy do dodania markerów. Markery na chybił trafił zostały dodane przez pomocniczą funkcję.

// GET latlng onClick

map.on('click', function (e) {
  console.log(e.latlng)
  alert(e.latlng)
})

Dodanie markerów do mapy

Poniżej kod js odpowiedzialny do wyświetlenia markerów na mapie.

// MARKERS

const markers = [
  [52.228956, 21.003799], 
  [52.258071, 20.986805], 
  [52.242728, 21.041565], 
  [52.234213, 21.029034], 
  [52.251661, 21.003456]
]

function colorMarker (color) {
  const svgTemplate = `
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="marker">
      <path stroke="#000000" fill="#${color}" d="M15.938 32S6 17.938 6 11.938C6 .125 15.938 0 15.938 0S26 .125 26 11.875C26 18.062 15.938 32 15.938 32zM16 6c-2.209 0-4 1.791-4 4s1.791 4 4 4 4-1.791 4-4-1.791-4-4-4z"/>
    </svg>`

  const icon = L.divIcon({
    className: 'marker',
    html: svgTemplate,
    iconSize: [40, 40],
    iconAnchor: [12, 24],
    popupAnchor: [7, -16]
  })

  return icon
}

markers.map((marker, index) => {
  const lat = marker[0]
  const lng = marker[1]
  L.marker([lat, lng], { icon: colorMarker(color[index]) }).bindPopup(`color: #${color[index]}<br>${label[index]}`).addTo(map)
})

Najpierw tablica składająca się z tablicy markerów.
Później funkcja do której przekazujemy kolor naszego markera a zwracany nam jest svg w odpowiednim kolorze.

Następnie za pomocą map dodajemy nasze markery do mapy. W tym miejscu również jest użyta funkcja z kolorowaniem markerów, jak i dodaniem popup do markera, który po kliknięciu się pojawia.

Poniżej cała mapa

See the Pen
leafleat-marker-svg-and-legend
by Greg (@Tomik23)
on CodePen.

Powiązane artykuły:

Alternatywa dla google maps – Open Street Map oraz Leaflet
Jak do Open Street Map i Leaflet dodać routing – OSRM
Użycie GeoJson z Leaflet
Dodawanie, przesuwanie i kasowanie markerów – Leaflet
Centrowanie mapy uwzględniając szerokość diva – fitBounds leaflet