Mapy 2: leafletjs

... Petr Blahoš, 31. 5. 2020 JavaScript

Pokud jste nečetli minulý článek o Google Maps, udělejte to teď. Hotovo? Tak se dáme do práce.

leaflet

Knihovna leaflet umí používat různé mapové podklady. Vyzkoušíme asi ten nejjednodušší příklad s podklady přímo z openstreetmap.org. Můžete ale použít i jiné podklady - čtěte sekci Data Providers ve FAQ.

<div id="map" class="map"></div>
<script>
function makeMap() {
  var center = [49.7477, 14.4025];
  var map = L.map('map').setView(center, 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);
  L.marker(center).addTo(map);
}
window.addEventListener('DOMContentLoaded', (event) => {
  makeMap();
});
</script>

Pokud chcete používat tento podklad od openstreetmap, dělejte to prosím v souladu s podmínkami použití.

Jak je vidět, vyrobit značku je přibližně stejně jednoduché, jako v Google Maps. Tak si, stejně jako minule, uděláme tři značky, a jednou z nich zkusíme pohybovat.

<div id="map" class="map"></div>
<script>
function makeMap() {
  var center = [49.7477, 14.4025];
  var map = L.map('map').setView(center, 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);
  var m1 = L.marker(center).addTo(map);
  var m2 = L.marker([49.7400, 14.4025]).addTo(map);
  var m3 = L.marker([49.7550, 14.4125]).addTo(map);

  var delta = 0.001;
  function moveMarker() {
    center[1] += delta;
    if (center[1] < 14.3 || center[1] > 14.5) {
      delta = -delta;
      center[1] += delta;
    }
    m1.setLatLng(center);
  }
  setInterval(moveMarker, 100);
}
window.addEventListener('DOMContentLoaded', (event) => {
  makeMap();
});
</script>

Jiná značka

A teď už nám jen zbývá prozkoumat, jak nastavit jinou barvu značky. Podle API to vypadá, že lze jako ikonu lze použít pouze bitmapový obrázek. Takže tentokrát žádné hraní s nastavením barev. Budeme si muset všechny ikony předpřipravit, a pak nastavit tu správnou.

<div id="map" class="map"></div>
<script>
function makeMap() {
  var center = [49.7477, 14.4025];
  var map = L.map('map').setView(center, 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);
  var icon1 = L.icon({
    iconAnchor: [12, 32],
    iconUrl: 'pin-red.png'
  });
  var icon2 = L.icon({
    iconAnchor: [12, 32],
    iconUrl: 'pin-pink.png'
  });
  var icon3 = L.icon({
    iconAnchor: [12, 32],
    iconUrl: 'pin-violet.png'
  });
  var m1 = L.marker(center, {icon: icon1, title: "Icon 1"}).addTo(map);
  var m2 = L.marker([49.7400, 14.4025], {icon: icon2, title: "Icon 2"}).addTo(map);
  var m3 = L.marker([49.7550, 14.4125], {icon: icon3, title: "Icon 3"}).addTo(map);
}
window.addEventListener('DOMContentLoaded', (event) => {
  makeMap();
});
</script>

Animace značek

Tady děláme vpodstatě totéž, co u Google Maps API. Vytvoříme značku, uložíme si k ní hodnotu. Pověsíme click event. Trošku složitější je práce s tooltipem. Zatímco Google Mapy nastavovaly tooltip pomocí setTitle, zde musíte ten tooltip explicitně vytvořit, a pak přes setTooltipContent případně měnit obsah. Při vytváření značky sice můžete zadat title, který pak funguje jako tooltip, ale nepodařilo se mi ho dynamicky měnit.

A ještě ikony. Jak jsem zmínil, nemáme vektorové ikony, takže jsem připravil několik bitmap, a ty střídám.

<div id="map" class="map"></div>
<script>
function makeMap() {
  var center = [49, 14];
  var map = L.map('map').setView(center, 10);
  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);

  var icons = [
    L.icon({ iconAnchor: [12, 32], iconUrl: 'pin-red.png' }),
    L.icon({ iconAnchor: [12, 32], iconUrl: 'pin-pink.png' }),
    L.icon({ iconAnchor: [12, 32], iconUrl: 'pin-green.png' }),
    L.icon({ iconAnchor: [12, 32], iconUrl: 'pin-violet.png' })
  ];
  var markers = {};
  for (var i = 1; i < 6; i++) {
    var mul = 2 == i ? 1.1 : i;
    var m = L.marker([49.0, 13.8 + 0.1*mul], {icon: icons[2]}).addTo(map);
    m.value = 160;
    m.bindTooltip("Initial: " + m.value);
    m.on("click", function (e) {
      console.log("Value on the clicked marker: ", this.value);
    });
    markers[i] = m;
  }
  function updateMarkers() {
    var m = markers[Math.floor(Math.random() * 5) + 1];
    m.value = Math.floor(Math.random() * 300);
    var zindex = 1;
    if (m.value < 75) {
      m.setIcon(icons[0]);
      zindex = 5;
    } else if (m.value < 150) {
      m.setIcon(icons[1]);
      zindex = 4;
    } else if (m.value > 200) {
      m.setIcon(icons[3]);
      zindex = 3;
    } else {
      m.setIcon(icons[2]);
    }
    m.setZIndexOffset(zindex);
    m.setTooltipContent("Value: " + m.value);
  }
  setInterval(updateMarkers, 1000);
}
window.addEventListener('DOMContentLoaded', (event) => {
  makeMap();
});
</script>

Co dál

Upřímně: sotva jsme se dotkli povrchu. Jak Google Maps API, tak leaflet toho umožňují mnohem víc. Tak se zvesela můžete dát do experimentování na jsfiddle.

Příště zkusíme zase totéž, ale bez mapových podkladů. Těšíte se?

Odkazy