Leaflet: „Sprechende“ Marker aus mehreren Bildern zusammensetzen?
Linuchs
- geolocation
Moin,
habe bei meiner Recherche keine Lösung gefunden, vermutlich gibt's auch keine. Sehr speziell.
Auf der Europakarte der Vereine unterscheide ich Mitglieder von Interessenten .
Wenn eine Hörprobe vorliegt, nehme ich stattdessen die Marker und
Bei Videos auf der Webseite zwei weitere Marker, macht sechs.
Nun können die Vereine ein kurzes Statement abgeben, wie sie mit Corona klarkommen. Dazu möchte ich den Markern einen Stern hinzufügen, was die Markerzahl nochmal verdoppelt.
Wäre fein, wenn ich einen Marker zusammensetzen könnte dort wo er definiert wird:
// Marker (Bild) definieren
var marker_blau_audio = L.icon({
iconUrl: 'img/marker_blau_audio_25_41.png',
shadowUrl: '',
iconSize: [25, 41], // size of the icon
shadowSize: [ 0, 0], // size of the shadow
iconAnchor: [12, 41], // point of the icon which will correspond to marker's location - rechts, oben
shadowAnchor: [ 0, 0], // the same for the shadow
popupAnchor: [ 0,-41] // point from which the popup should open relative to the iconAnchor
});
Gruß, Linuchs
Hallo Linuchs,
das einzige, was mir einfiele, wäre eine Overlaytechnik. Dafür hast Du einen roten oder blauen Basismarker, und legst nach Bedarf Symbole für Audio, Video oder Sternchen mit transparentem Hintergrund darüber. Das können GIF oder PNG mit transparentem Hintergrund sein, oder SVGs (für IE11 Unterstützung müssen die SVGs passend gebaut sein).
D.h. entweder hast Du bei 500 Vereinen 500 Marker, aber 12 verschiedene Icons für die Marker und weitere Verdopplungen, wenn noch was dazu kommt. Oder Du hast nur 5 Icons (rot, blau, audio-Overlay, video-Overlay, corona-Overlay), von denen Du pro Verein 1-3 Stück zeigst. Das kann man so lösen, dass Du an dem HTML Element mit dem Marker darin Klassen setzt, und im CSS je nach gesetzten Klassen das background-image zurechtstapelst. Oder mit ::after und ::before Zusatzebenen hinzufügst. Wenn es nur audio/video und corona ist, kommt man mit ::before und ::after gerade so hin 😀:
Allerdings: die Zugänglichkeit dieser Konstruktion - oder generell der Marker-Konstruktion - müsste man noch genauer betrachten. Entweder durch visuell versteckten Text im div oder durch geeignete aria-Attribute.
<div class="marker red audio corona" style="top:...; left: ..."></div>
.marker {
position: absolute;
width: ..., height: ...;
}
.marker.red {
background-image: red-icon.png;
}
.marker.blue {
background-image: red-icon.png;
}
.marker.audio::before {
position:absolute;
background-image: audio-icon.png;
z-index: 1;
}
.marker.video::before {
position:absolute;
background-image: audio-icon.png;
z-index: 1;
}
.marker.infos::after {
position:absolute;
background-image: infos-icon.png;
z-index: 2;
}
Also - viele Icons oder Stapeltechnik, für eins von beiden musst Du Dich wohl entscheiden. Wie setzt Du die Marker? Per JS am Client? Oder erzeugst Du das HTML dafür am Server mit PHP? Wenn es PHP ist, würde ich bei vielen unterschiedlichen Icons bleiben, auf diese Weise transferierst Du deutlich weniger HTML. Wenn es JS ist, dann würde ich sagen: es ist netzwerktechnisch egal, du sparst Dir nur die Arbeit, viele Iconvarianten zu pflegen.
Rolf
Hallo Rolf,
einen roten oder blauen Basismarker, und legst nach Bedarf Symbole für Audio, Video oder Sternchen mit transparentem Hintergrund darüber.
Ging mir auch durch den Kopf. Dann wäre aber der Basismarker nicht mehr anklickbar, weil er abgedeckt ist. Man könnte ihn vielleicht transparent oben drauflegen ...
Wie setzt Du die Marker? Per JS am Client?
Genau. Die (hunderte) Marker werden per CSV-String an den Client übergeben. Kannst du im HTML-Code sehen. Wird erstaunlich flott vom Client platziert.
Mit deinem ::before und ::after experimentiere ich, wenn die Idee von Jürgen nicht funktioniert, etwas an den Basismarker „anzukleben“.
Gruß Linuchs
Hallo Rolf B,
das einzige, was mir einfiele, wäre eine Overlaytechnik.
Ein Sprite oder gestapelte Hintergrundgrafiken wären auch denkbar.
Bis demnächst
Matthias
Hallo ihr beiden,
das einzige, was mir einfiele, wäre eine Overlaytechnik.
Ein Sprite oder gestapelte Hintergrundgrafiken wären auch denkbar.
es ist hier vieles denkbar, aber das Mittel der Wahl ist das, was Leaflet dafür vorgesehen hat: divIcon
Gruß
Jürgen
Hallo JürgenB,
ok, Leaflet kenne ich nicht und wusste auch nicht (mehr), dass Linuchs das einsetzt. Daher kam ich mit "Bordmitteln" an.
Rolf
Hallo Linuchs,
kennst du L.divIcon
? Mit folgendem Code ertstelle ich ein Icon mit Text (label) darüber, nur mal so als Anregung:
Cluster_Icon = { icon: { anchor: {x:16,y:16}, url: baseurl+"Icons/cluster.svg",
scaledSize: { width: 31, height: 31, widthUnit: "px", heightUnit: "px" },
size: { width: 31, height: 31, widthUnit: "px", heightUnit: "px" } } };
icon = Cluster_Icon;
JB.Map.prototype.setClusterMarker = function(coord,icon,title,label) {
var url = icon.icon.url;
var w = icon.icon.size.width + icon.icon.size.widthUnit;
var h = icon.icon.size.height + icon.icon.size.heightUnit;
var marker = [];
var html = "<div style='background-image:url("+url+");background-repeat: no-repeat;width:"+w+";height:"+h+"'><div>"+label+"</div></div>";
var thisicon = L.divIcon({className:"JBcluster-icon", html: html, iconAnchor: [icon.icon.anchor.x, icon.icon.anchor.y] });
marker[0] = L.marker(coord, {icon: thisicon, title: title, zIndexOffset: 500 } );
marker[0].addTo(this.map);
return marker;
} // setClusterMarker
div.JBcluster-icon > div { display: flex; align-items: center; justify-content: center; font-weight: bold }
Gruß
Jürgen
Hallo Jürgen,
sieht sehr kryptisch aus.
Kannst du bitte mal einen Link nennen oder hier ein Bild der Marker posten?
Gruß, Linuchs
Habe hier mal etwas rumgespielt mit diesem Ergebnis:
Doch der Stern ist ein vollkommen eigenständiger HTML-Marker, der mit eigenem lat/lon platziert werden muss. Je nach Zoom-Faktor dürfte er näher oder weiter vom Haupt-Marker entfernt sein, das konnte ich bei jsfiddle nicht testen.
Geht das auch als Anhängsel zum vorhandenen Marker?
Linuchs
Hallo Linuchs,
Habe hier mal etwas rumgespielt mit diesem Ergebnis:
Doch der Stern ist ein vollkommen eigenständiger HTML-Marker, der mit eigenem lat/lon platziert werden muss. Je nach Zoom-Faktor dürfte er näher oder weiter vom Haupt-Marker entfernt sein, das konnte ich bei jsfiddle nicht testen.
Geht das auch als Anhängsel zum vorhandenen Marker?
ja, siehe meine andere Antwort.
Ansonsten kannt du den Ursprung des Icons ja auch in Pixeln angeben und so Marker und Stern an die gleichen Koordinaten setzen, den Stern dann aber etwas weniger als die halbe Größe des Markers verschieben.
Gruß
Jürgen
Hallo Linuchs,
https://www.j-berkemeier.de/GPXViewer/Beispiel9.html
Die roten Icons mit der Zahl in der Mitte sind mit dem gezeigten Code erstellt.
Ich verwende die Methode L.divIcon
, um die Icons zu erstellen. Dabei wird eigentlich nur ein HTML-Element frei auf der Karte positioniert.
var html = "<div style='background-image:url("+url+");background-repeat: no-repeat;width:"+w+";height:"+h+"'><div>"+label+"</div></div>";
var thisicon = L.divIcon({className:"JBcluster-icon", html: html, iconAnchor: [icon.icon.anchor.x, icon.icon.anchor.y] });
erstellt das Icon. Die URL und weitere Parameter wie Offset und Größe hole ich aus einer Datenstruktur.
Ich nehme als Grundelement ein div mit Hintergrundbild, und als Inhalt den Text.
marker[0] = L.marker(coord, {icon: thisicon, title: title, zIndexOffset: 500 } );
erzeugt dann das Icon, das sich wie ein "normales" Icon verhält.
Gruß
Jürgen
Hallo JürgenB,
nun gut, aber das ist die Leaflet-spezifische Hülle um das Ganze.
Im Inneren besteht wieder das ursprüngliche Problem. Viele verschiedene Icons, oder die Montage mehrerer Layer zu einem Bild. So wie von mir oben schon angesprochen.
Und viel inline style, der vermutlich gerne im Stylesheet landen möchte.
Rolf