zur besseren Übersicht deaktivieren wir die vier anderen Layer indem wir den Aufruf der jeweiligen Funktion auskommentieren und die Funktion im VS Code einklappen
wir könnten, wie in der Leaflet Dokumentation von L.geoJSON im Usage example gezeigt, das Popup einfach vor dem .addTo(overview)
hinzufügen, das machen wir aber nicht, denn in einem späteren Schritt würde uns das nur Probleme bereiten. Deshalb verwenden wir das Options-Objekt und werden bei pointToLayer fündig. Die Description zeigt uns ein passendes Beispiel, wie wir den Marker besser kontrollieren können.
L.geoJSON(geojson, {
pointToLayer: function(geoJsonPoint, latlng) {
return L.marker(latlng);
}
}).addTo(overlay);;
der Funktion, die bei pointToLayer
für jeden Punkt des Datensatzes ausgeführt wird, wird von Leaflet automatisch der aktuelle Punkt (geoJsonPoint
) und seine Koordinate (latlng
) übergeben
am Ende der Funktion müssen wir den Marker mit return
zurückgeben damit er in der Karte auch gezeichnet wird
das Popup definieren in Template-Syntax mit Backticks vor dem Marker in einer Variablen popup
und hängen es mit bindPopup
an den Marker. Wir erinnern uns daran, wie wir die Attribute des Punkts ansprechen können (z.B. geoJsonPoint.properties.NAME
) und verwenden die Attribute NAME
, ADRESSE
, THUMBNAIL
, WEITERE_INF
für das Popup
let popup = `
<img src="${geoJsonPoint.properties.THUMBNAIL}" alt=""><br>
<strong>${geoJsonPoint.properties.NAME}</strong>
<hr>
Adresse: ${geoJsonPoint.properties.ADRESSE}<br>
<a href="${geoJsonPoint.properties.WEITERE_INF}" target="Wien">Weblink</a>
`;
return L.marker(latlng).bindPopup(popup);
alt=""
bedeutet, dass unser Bild rein dekorativ ist. Wir wissen ja auch gar nicht, was auf den einzelnen Bildern zu sehen ist.
target="Wien"
bewirkt wie beim Neuseelandbeispiel, dass alle Weblinks im selben Tab geöffnet werden
damit ist das Popup fertig, als nächstes verwenden wir ein eigenes Icon an Stelle der Marker
als Quelle für unser Icon verwenden wir die Map Icons Collection - 1000+ free & customizable icons for maps
Suche photo -> Photo wählen
wir versuchen gleich das customizable Feature und wählen Weiß (#ffffff
) als Farbe beim Farbwähler und klicken auf Generate
die Seite wird neu geladen, die Icons entsprechend angepasst und wir finden unsere Farbe in der URL https://mapicons.mapsmarker.com/markers/media/photo/?custom_color=ffffff wieder - dieses Feature werden wir später bei den Icons für die Bushaltestellen noch brauchen …
wir wählen das linke Icon und speichern es im icons/
-Verzeichnis als photo.png
eingebaut wird das Icon beim Erzeugen des Markers - die Dokumentation von L.marker zeigt bei den Options, dass wir icon
als Option definieren müssen. Wie dieses Icon von der Syntax her aussehen muss, zeigt der Link zur Dokumentation von L.icon in der Description der Option icon
. Wir folgen dem Link und sehen ein komplettes Usage example von dem wir zunächst nur die Option iconUrl
verwenden - sie zeigt auf unser Icon photo.png
im Verzeichnis icons/
return L.marker(latlng, {
icon: L.icon({
iconUrl: "icons/photo.png",
})
}).bindPopup(popup);
die Optionen iconAnchor
, popupAnchor
beim Beispiel der Dokumentation weisen darauf hin, dass die Positionierung des Icons verändert werden kann. Per Default werden die Koordinaten des Punkts auf die linke, obere Ecke des Icons gesetzt - das schauen wir uns an und fügen temporär einen zweiten default Marker an der selben Position hinzu
L.marker(latlng).addTo(map); // temporär zum Testen des Anfasspunkts
let mrk = L.marker(latlng, {
// ...
});
die Spitze unseres Icons mit der Größe 32x37 Pixel liegt von Links, Oben gesehen bei 16 und 37, diese Werte verwenden wir beim iconAnchor
Array
icon: L.icon({
iconUrl: "icons/photo.png",
iconAnchor: [16, 37],
})
wenn wir auf das Popup klicken, verdeckt das Popup das Icon, deshalb schieben wir es beim popupAnchor
Array um 37 Pixel nach Oben
icon: L.icon({
iconUrl: "icons/photo.png",
iconAnchor: [16, 37],
popupAnchor: [0, -37]
})
damit sind Icon und Popup richtig positioniert und wir können den temporären Marker löschen oder auskommentieren. der fertige Code für unser Icon sieht so aus:
return L.marker(latlng, {
icon: L.icon({
iconUrl: "icons/photo.png",
iconAnchor: [16, 37],
popupAnchor: [0, -37]
})
}).bindPopup(popup);
Bevor wir weiterarbeiten, setzen wir den Zoomfaktor beim Laden der Karte auf 16 und Blicken damit auf die Wiener Innenstadt
als Quelle für das Bus Icon verwenden wir wieder die Map Icons Collection - 1000+ free & customizable icons for maps, suchen nach photo, stellen #ffffff
als Farbe ein und speichern uns das neu generierte Icon als bus.png
in dass Verzeichns icons
Den Haltestellenlayer erzeugen wir mit Copy-Paste des Codes der Sehenswürdigkeiten und ein paar kleinen Änderungen in vier Schritten
wir kopieren den geamten L.geoJSON()
Code der Sehenswürdigkeiten und überschreiben damit den bestehenden L.geoJSON()
Aufruf in der Funktion loadStops
wir bessern den Popup-Code aus und verwenden die Attribute STAT_NAME
und LINE_NAME
wir bessern die iconUrl
aus und verwenden icons/bus.png
statt icons/photo.png
wir löschen den Kommentar beim Funktionsaufruf loadStops("https://...")
und aktivieren damit das Zeichnen des Haltestellen Layers
L.geoJSON(geojson, {
pointToLayer: function(geoJsonPoint, latlng) {
let popup = `
<strong>${geoJsonPoint.properties.LINE_NAME}</strong><br>
Station ${geoJsonPoint.properties.STAT_NAME}
`;
return L.marker(latlng, {
icon: L.icon({
iconUrl: "icons/bus.png",
iconAnchor: [16, 37],
popupAnchor: [0, -37]
})
}).bindPopup(popup);
}
}).addTo(overlay);
loadStops("https://data.wien.gv.at/daten/geo?service=WFS&request=GetFeature&version=1.1.0&typeName=ogdwien:TOURISTIKHTSVSLOGD&srsName=EPSG:4326&outputFormat=json");
Ein Blick auf die Attribute der Bushaltestellen zeigt, dass zusätzlich zum Namen der Linie in LINIE_NAME
, jede Linie eine LINIE_ID
besitzt, deren Werte von 1 bis 6 gehen.
Diese LINE_ID
wird entscheiden, welches Icon wir verwenden und deshalb generieren wir bei der Map Icons Collection sechs Icons mit passenden Farben der Webseite Colors - A nicer color palette for the web
Übungsaufgabe: 6 Icons nach folgenden Vorgaben erzeugen
icons/
bus_1.png
bis bus_6.png
Lösung für die URLs bei der Map Icons Collection
Damit bleibt noch, die Icons je nach LINE_ID
zu verwenden, wir bedienen uns wieder der Template-Syntax mit Backticks bei der iconUrl
und erzeugen Links zu den Icons bus_1.png
bis bus_6.png
. Die Zahl, und damit die Farbe, folgt dem Attribut LINE_ID
icon: L.icon({
iconUrl: `icons/bus_${geoJsonPoint.properties.LINE_ID}.png`,
// ...
})
Bevor wir die Funktion laodHotels
verändern, besorgen wir uns drei Icons für die Hotels und Unterkünfte und speichern sie im Verzeichnis icons/
Icon Hotel, Farbe PURPLE - #B10DC9
, Icon hotel_0star
Icon Pension, Farbe PURPLE - #B10DC9
, Icon lodging_0star
Icon Appartment, Farbe PURPLE - #B10DC9
, Icon apartment-2
Danach erzeugen wir den Layer für Hotels und Unterkünfte wieder mit Copy-Paste, diesmal des Codes der Haltestellen und ein paar kleinen Änderungen in den bekannten vier Schritten
L.geoJSON()
Code der Haltestellen und überschreiben damit den bestehenden L.geoJSON()
Aufruf in der Funktion loadHotels
wir bessern den Popup-Code aus und verwenden die Attribute ADRESSE
, BETRIEB
, BETRIEBSART_TXT
, KATEGORIE_TXT
, KONTAKT_EMAIL
, KONTAKT_TEL
, und, WEBLINK1
let popup = `
<p>
<strong>
${geoJsonPoint.properties.BETRIEB} -
${geoJsonPoint.properties.BETRIEBSART_TXT}
${geoJsonPoint.properties.KATEGORIE_TXT}
</strong>
<br>
${geoJsonPoint.properties.ADRESSE}
</p>
<hr>
<address>
Tel.:${geoJsonPoint.properties.KONTAKT_TEL}<br>
E-Mail: <a href="mailto:${geoJsonPoint.properties.KONTAKT_EMAIL}">${geoJsonPoint.properties.KONTAKT_EMAIL}</a><br>
Web: <a href="${geoJsonPoint.properties.WEBLINK1}" target="Wien">${geoJsonPoint.properties.WEBLINK1}</a>
</address>
`;
target="Wien"
bewirkt wieder, dass alle Weblinks im selben Tab geöffnet werdeniconUrl
aus und verwenden vorerst icons/hotel_0star.png
statt icons/bus.png
für alle Icons. Die Unterscheidung nach Typen folgt späterloadHotels("https://...")
und aktivieren damit das Zeichnen des Hotel LayersBleibt noch, die Hotels und Unterkünfte nach Typen zu unterscheiden. Dazu verwenden wird das Attribut BETRIEBSART
und ermitteln in einem if, else if, else
Block das passende Icon für die Werte H (Hotel), P (Pension) und A (Appartment). Wir speichern den gefundenen Icon-Namen in einer Variablen icon
, die wir vor der if-Abfrage initialisieren.
let icon;
if (geoJsonPoint.properties.BETRIEBSART == "H") {
icon = "hotel_0star";
} else if (geoJsonPoint.properties.BETRIEBSART == "P") {
icon = "lodging_0star";
} else {
icon = "apartment-2";
}
Den gefundenen Icon-Namen setzen wir schließlich bei der iconUrl
ein. Damit werden je nach Typ, verschiedene Icons angezeigt.
icon: L.icon({
iconUrl: `icons/${icon}.png`,
// ...
})