Úloha 3 – VS Code. Mapová aplikace v prostředí Leaflet
Výběr nejoblíbenějších JS mapových knihoven
-
Lehká a výkonná knihovna pro interaktivní mapy.
Je jednoduchá na použití a vhodná pro většinu projektů.
-
Výkonná knihovna pro vytváření dynamických aplikací.
Vhodná pro rozsáhlé a komplexní GIS aplikace.
-
Vykreslování interaktivních map pomocí WebGL.
Ideální pro aplikace, které potřebují svižné 3D vizualizace a vlastní stylování map.
-
Vhodná pro 3D aplikace či interaktivní analýzu terénu.
Perfektní pro aplikace, které vyžadují realistickou 3D vizualizaci.
VS Code
Visual Studio Code (VS Code) je bezplatný a multiplatformní editor zdrojového kódu, který vyvinula společnost Microsoft. Je populární díky flexibilitě a podpoře široké škály programovacích jazyků.
Mezi výhody patří zvýraznění syntaxe, našeptávání při psaní, ladění kódu přímo z editoru a možnost instalace řady rozšíření (např. Live Server).
Mapová aplikace v prostředí Leaflet
0) Příprava struktury souborů
Na disku si vytvoříme prázdnou složku, ve které budeme uchovávat veškeré soubory spojené s tímto cvičením (html, js a css soubory + např. obrázky pro ikony). Ideálně volíme umístění na vlastním disku H.
-
nový soubor
index.html
-
nový soubor
script.js
- zatím ponecháme prázdný -
nový soubor
style.css
- zatím ponecháme prázdný
1) Zobrazení jednoduchého mapového okna
Do souboru index.html
je potřeba připojit knihovnu Leaflet v hlavičce souboru (head). Dále musíme v sekci body vložit mapové okno a připojit skript odkazující na ovládání mapy.
...
<head>
...
<!-- Externí připojení CSS symbologie Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<!-- Externí připojení JS knihovny -> vložit až po připojení CSS souboru -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
...
</head>
...
<body>
...
<!-- Vložení divu pro zobrazení mapového okna -->
<div id="map"></div>
<!-- Připojení JS scriptu ovládajícího mapové okno -->
<script src="script.js"></script>
</body>
Ve script.js
vytvoříme proměnnou mapy, nastavíme její střed a úroveň přiblížení. Dále určíme podkladovou mapu, maximální úroveň přiblížení a popis datového zdroje.
// Nastavení mapy, jejího středu a úrovně přiblížení
var map = L.map('map').setView([50.104, 14.388], 13);
// Určení podkladové mapy, maximální úrovně přiblížení a zdroje dat
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
Pomocí style.css
upravíme velikost mapového okna dle potřeb.
Stav kódu po dokončení kroku 1) Zobrazení jednoduchého mapového okna
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<!-- Externí připojení CSS symbologie Leaflet-->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<!-- Externí připojení JS knihovny -> vložit až po připojení CSS souboru -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<title>Moje první Leaflet mapa</title>
</head>
<body>
<h1>Pěkná mapa v Leafletu</h1>
<div id="map"></div>
<script src="script.js"></script>
</body>
</html>
// Nastavení mapy, jejího středu a úrovně přiblížení
var map = L.map('map').setView([50.104, 14.388], 13);
// Určení podkladové mapy, maximální úrovně přiblížení a zdroje dat
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
2) Vykreslení útvarů v mapě
Pomocí kódu je možné do mapy přidat body, linie či polygony různých tvarů. Data můžeme buď zadat manuálně nebo načíst ze souboru, např. z formátu GeoJSON. Tomu se budeme věnovat v příštím cvičení, nyní nám postačí ruční zadání.
Nejprve přidáme obyčejný marker, aneb bod v mapě. Například pro polohu FSv ČVUT v Praze, jejíž souřadnice vyčteme z Google Map.
V kroku 3 budeme marker vylepšovat, ale nejprve zkusíme vykreslit obdobným způsobem linii a polygony.
Vykreslíme několik bodů na základě jejich souřadnic. Následně je spojíme do polyline. V dokumentaci najdeme také parametry vizualizace linie.
Následně zkusíme upravit barvu a styl linie spojující body.
Dále vytvoříme polygon spojující zadané body a opět upravíme jeho styl s pomocí dokumentace.
Nově vytvořená vrstva (tedy níže v kódu) se v mapě vykreslí nad předchozí vrstvu. V tomto případě je tedy linie zobrazená pod polygonem.
Stav kódu po dokončení kroku 2) Vykreslení útvarů v mapě
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<!-- Externí připojení CSS symbologie Leaflet-->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<!-- Externí připojení JS knihovny -> vložit až po připojení CSS souboru -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<title>Moje první Leaflet mapa</title>
</head>
<body>
<h1>Pěkná mapa v Leafletu</h1>
<div id="map"></div>
<script src="script.js"></script>
</body>
</html>
// Nastavení mapy, jejího středu a úrovně přiblížení
var map = L.map('map').setView([50.104, 14.388], 13);
// Určení podkladové mapy, maximální úrovně přiblížení a zdroje dat
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
// Bod zobrazující FSv ČVUT v Praze
var marker = L.marker([50.104, 14.388]).addTo(map);
// Body
var points = [
[50.104, 14.388], // FSv ČVUT v Praze
[50.091, 14.402], // Pražský hrad
[50.082, 14.426], // metro Můstek
[50.106, 14.437] // vlak Praha Holešovice-zastávka
];
// Linie propojující několik bodů
var line = L.polyline(points, {color: "red", weight: 10}).addTo(map);
// Polygon se zadanými vrcholy
var polygon = L.polygon(points, {color: "blue", weight: 3, fillColor: "lightblue", fillOpacity: "0.8"}).addTo(map);
3) Pop-up
Nejprve zobrazíme markery pro všechny body v poli points
. To je možné provést postupně po jednom (jako v prvním kroku) nebo automatizovaně.
V kódu výše se pro každý bod z pole points
vytvoří marker v mapě. Proměnná coords
(coordinates) představuje každý jednotlivý prvek (bod = dvojice souřadnic) v poli points
během iterace pomocí funkce forEach()
.
Následně je možné smazat či vložit do blokového komentáře předchozí zadání markeru na FSv ČVUT.
Dále přiřadíme pop-up jednomu prvku v mapě. Například polygonu, který spojuje všechny naše body.
Podobně bychom mohli postupně přiřadit pop-up jiným prvkům v mapě. Nicméně vyzkoušíme automatizovaný popis bodů z pole points
.
Prvním krokem je úprava zadání bodového pole. Souřadnice vložíme do proměnné coords
, kterou jsme už předtím využívali. Zároveň přidáme textový parametr.
Následně bude nutné vůči této úpravě přizpůsobit vykreslení linie a polygonu, což provedeme přidání tzv. arrow funkce.
Výše použitá arrow funkce přijme každý objekt p
z pole points
a vrátí hodnotu jeho vlastnosti coords
.
Nyní je kód opět funkční ve vykreslení linie a polygonu. Zbývá upravit markery, pro které je potřeba drobně upravit funkci forEach()
.
Upozornění
Pozor, uvnitř iterace funkce forEach()
pracujeme s proměnnou jednoho zvoleného bodu point
, ne se všemy body ze seznamu points
.
Závěrem tohoto kroku vytvoříme nový a samostatný marker s vlastní ikonou, kterou si v ve formátu png s průhledným pozadím stáhneme z internetu.
Pomocí dokumentace můžeme upravit styl markeru (ikony).
// Nastavení parametrů vlastního markeru
var blackMarker = L.icon({
iconUrl: '/assets/cerny_popup.png', // Umístění obrázku na disku
iconSize: [60, 60], // Velikost ikony v px
iconAnchor: [0, 80], // Pozice, na které se zobrazí ikona - vůči bodu
popupAnchor: [5, -100] // Pozice, ze které se popup otevře - vůči bodu
});
// Samostatný bod s novým značením
var markerDivokaS = L.marker([50.093, 14.324], {icon: blackMarker}).addTo(map);
markerDivokaS.bindPopup("Zde je <b style='color: red;'>Divoká Šárka</b>");
Upozornění
Při zápisu textu v pop-upu je nutné využít dvojité uvozovky "..."
pro textový řetězec a jednoduché '...'
pro případné určený stylu (= barvy).
Při použití dvou párů dvojitých uvozovek by nastala chyba, protože by nebylo jasné, kdy má být textový řetězec ukončen.
Stav kódu po dokončení kroku 3) Pop-up
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<!-- Externí připojení CSS symbologie Leaflet-->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<!-- Externí připojení JS knihovny -> vložit až po připojení CSS souboru -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<title>Moje první Leaflet mapa</title>
</head>
<body>
<h1>Pěkná mapa v Leafletu</h1>
<div id="map"></div>
<script src="script.js"></script>
</body>
</html>
// Nastavení mapy, jejího středu a úrovně přiblížení
var map = L.map('map').setView([50.104, 14.388], 13);
// Určení podkladové mapy, maximální úrovně přiblížení a zdroje dat
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
// Body s textovými informacemi
var points = [
{ coords: [50.104, 14.388], text: "FSv ČVUT v Praze" },
{ coords: [50.091, 14.402], text: "Pražský hrad" },
{ coords: [50.082, 14.426], text: "metro Můstek" },
{ coords: [50.106, 14.437], text: "vlak Praha Holešovice-zastávka" }
];
// Linie propojující několik bodů
var line = L.polyline(points.map(p => p.coords), {color: "red", weight: 10}).addTo(map);
// Polygon se zadanými vrcholy
var polygon = L.polygon(points.map(p => p.coords), {color: "blue", weight: 3, fillColor: "lightblue", fillOpacity: "0.8"}).addTo(map);
// Pop-up pro polygon
polygon.bindPopup("Toto je polygon");
// Přidání markerů s popisky pro každý bod
points.forEach(function(point) {
L.marker(point.coords).addTo(map).bindPopup(point.text);
});
// Nastavení parametrů vlastního markeru
var blackMarker = L.icon({
iconUrl: '/assets/cerny_popup.png', // Umístění obrázku na disku
iconSize: [60, 60], // Velikost ikony v px
iconAnchor: [0, 80], // Pozice, na které se zobrazí ikona - vůči bodu
popupAnchor: [30, -100] // Pozice, ze které se popup otevře - vůči bodu
});
// Samostatný bod s novým značením
var markerDivokaS = L.marker([50.093, 14.324], {icon: blackMarker}).addTo(map);
markerDivokaS.bindPopup("Zde je <b style='color: red;'>Divoká Šárka</b>");
4) Přidání mapových vrstev
Katalog různých podkladových map nalezneme ZDE. Stačí v pravém menu vybrat mapu a následně zkopírovat její parametry v js kódu.
Zkopírované parametry podkladové mapy vložíme do JavaScriptu.
// Definice podkladové OpenTopoMap
var otm = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
maxZoom: 17,
attribution: 'Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
});
// Přiání OpenTopoMap do mapy
otm.addTo(map);
Následně je potřeba upravit definici původní OpenStreetMap na začátku skriptu přiřazením názvu, např. osm
.
Jako třetí podkladovou vrstvu přidáme Ortofoto ČR z ČÚZK. Tato vrsta je dostupná jako WMS služba, tudíž ji musíme přidat s trochu jinými parametry než předchozí OpenTopoMap.
Parametry vrstvy layers
, format
a transparent
nalezneme ve vlastnostech služby GetCapabilities
.
Nyní na konec skriptu vložíme přepínání podkladových vrstev.
Nyní se nabídka přepnutí map zobrazí po najetí kurzoru myši na ikonu mapových vrstev. Jestliže bychom chtěli vidět přepínání vrstev stále zobrazené, pak přidáme úpravu parametru collapsed
.
Prvním parametrem níže upraveného přepínání je proměnná podkladových map (baseMaps
), druhým proměnná mapových vrstev (zatím jsme neučili, proto null
) a následuje volitelné nastavení, tedy např collapsed
.
Při načtení stránky se v podkladu zobrazí OpenTopoMap, která byla v kódu přidaná jako poslední.
Závěrem ještě přidáme přepínání i pro mapové vrstvy, tedy body, linii a polygon.
Následně musíme přepsat druhý parametr v přepínání vrstev z null
na overlayMaps
, tedy přidat mapové vrstvy jako součást přepínání.
// Proměnná uchovávající mapové vrstvy, které chceme zobrazovat a skrývat
var overlayMaps = {
"Divoká Šárka": markerDivokaS,
"Moje linie": line,
"Můj polygon": polygon
};
// Grafické přepínání podkladových map
var layerControl = L.control.layers(baseMaps, overlayMaps, {collapsed: false}).addTo(map);
Pokud bychom chtěli do přepínání vložit i body dávkově zobrazené funkcí forEach()
, pak je třeba tyto body nejdříve shluknout do jedné skupiny, se kterou budeme pracovat jako s celkem.
Zároveň je třeba upravit funkci forEach()
tak, aby se každý bod nepřiřadil hned do mapy, ale do skupiny markersLayer
. Až na dalším řádku všechny body dohromady vložíme do mapy.
Posledním krokem je pak přidání skupiny bodů markersLayer
do výběru vrstev.
Upozornění
Pokud chceme mít nějakou vrstvu skrytou při načtení mapy, pak ji jednoduše nepřidáváme do mapy v kódu pomocí vrstva.addTo(map)
, ale zobrazíme ji pouze výběrem vrstev.
Stav kódu po dokončení kroku 4) Přidání mapových vrstev
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<!-- Externí připojení CSS symbologie Leaflet-->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<!-- Externí připojení JS knihovny -> vložit až po připojení CSS souboru -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<title>Moje první Leaflet mapa</title>
</head>
<body>
<h1>Pěkná mapa v Leafletu</h1>
<div id="map"></div>
<script src="script.js"></script>
</body>
</html>
// Nastavení mapy, jejího středu a úrovně přiblížení
var map = L.map('map').setView([50.104, 14.388], 13);
// Určení podkladové mapy, maximální úrovně přiblížení a zdroje dat
var osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
// Definice podkladové OpenTopoMap
var otm = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
maxZoom: 17,
attribution: 'Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
});
// Přiání OpenTopoMap do mapy
//otm.addTo(map);
// Přidání ortofota jako WMS služby, určení vrstvy, formátu a průhlednosti
var ortofoto = L.tileLayer.wms("https://ags.cuzk.gov.cz/arcgis1/services/ORTOFOTO/MapServer/WMSServer", {
layers: "0",
format: "image/png",
transparent: true,
attribution: "© ČÚZK"
});
// Body s textovými informacemi
var points = [
{ coords: [50.104, 14.388], text: "FSv ČVUT v Praze" },
{ coords: [50.091, 14.402], text: "Pražský hrad" },
{ coords: [50.082, 14.426], text: "metro Můstek" },
{ coords: [50.106, 14.437], text: "vlak Praha Holešovice-zastávka" }
];
// Linie propojující několik bodů
var line = L.polyline(points.map(p => p.coords), {color: "red", weight: 10}).addTo(map);
// Polygon se zadanými vrcholy
var polygon = L.polygon(points.map(p => p.coords), {color: "blue", weight: 3, fillColor: "lightblue", fillOpacity: "0.8"}).addTo(map);
// Pop-up pro polygon
polygon.bindPopup("Toto je polygon");
// Vytvoření vrstvy pro markery
var markersLayer = L.layerGroup();
// Přidání markerů s popisky pro každý bod
points.forEach(function(point) {
L.marker(point.coords).bindPopup(point.text).addTo(markersLayer);
});
// Vložení skupiny bodů do mapy
markersLayer.addTo(map);
// Nastavení parametrů vlastního markeru
var blackMarker = L.icon({
iconUrl: '/assets/cerny_popup.png', // Umístění obrázku na disku
iconSize: [60, 60], // Velikost ikony v px
iconAnchor: [0, 80], // Pozice, na které se zobrazí ikona - vůči bodu
popupAnchor: [30, -100] // Pozice, ze které se popup otevře - vůči bodu
});
// Samostatný bod s novým značením
var markerDivokaS = L.marker([50.093, 14.324], {icon: blackMarker}).addTo(map);
markerDivokaS.bindPopup("Zde je <b style='color: red;'>Divoká Šárka</b>");
// Proměnná uchovávající podkladové mapy, mezi kterými chceme přepínat
var baseMaps = {
"OpenStreetMap": osm, // "popis mapy": nazevPromenne
"OpenTopoMap": otm,
"Ortofoto ČR": ortofoto
};
// Proměnná uchovávající mapové vrstvy, které chceme zobrazovat a skrývat
var overlayMaps = {
"Zajímavá místa": markersLayer,
"Divoká Šárka": markerDivokaS,
"Moje linie": line,
"Můj polygon": polygon
};
// Grafické přepínání podkladových map
var layerControl = L.control.layers(baseMaps, overlayMaps, {collapsed: false}).addTo(map);