Styling on-click marker on Python Folium map

Recently I’ve explained to you how to launch Google Street View from any place on the Folium map. Today it’s the time for continuation – styling the on-click marker, which can be applied to any other on-click marker provided to the Folium map.
Let’s get started with the code discussed in the previous article (break lines not included!):

class ClickForOneMarker(folium.ClickForMarker):
_template = Template(u"""
{% macro script(this, kwargs) %}
var new_mark = L.marker();
function newMarker(e){
new_mark.setLatLng(e.latlng).addTo({{this._parent.get_name()}});
new_mark.setZIndexOffset(-1);
new_mark.on('dblclick', function(e){
{{this._parent.get_name()}}.removeLayer(e.target)})
var lat = e.latlng.lat.toFixed(4),
lng = e.latlng.lng.toFixed(4);
new_mark.bindPopup(
"<a href=https://www.google.com/maps?layer=c&cbll=" + lat + "," + lng + " target=blank><img src=img/streetview.svg width=70 title=StreetView class=StreetViewImage></img></a>",{
maxWidth: "auto",
className: 'StreetViewPopup'
});
};
{{this._parent.get_name()}}.on('click', newMarker); 
{% endmacro %}
""") # noqa

def __init__(self, popup=None):
super(ClickForOneMarker, self).__init__()
self._name = 'Google Street View'

gsv = ClickForOneMarker()
map.add_child(gsv)

which opens a marker for us when clicked anywhere on the map (Pic. 1).

Python folium on-click marker with Street View access

Pic. 1 Python Folium on-click marker with some features provided.

Now, we are attending to styling both the marker as well as the popup. In this case, we will need to define the separate icon and inject some individual CSS styling for the popup content.
One of the nice ways of changing the default on-click marker icon is using the FontAwesome options, which are indeed available for Leaflet maps. As we know, everything, that happens inside of the jinja2 Template {% macro script(this, kwargs) %} reflects the Leaflet JavaScript code.
Let’s add the Font Awesome icon to our marker:

 _template = Template(u"""
{% macro script(this, kwargs) %}
const fontAwesomeIcon = L.divIcon({
html: '<i class="fa-sharp fa-solid fa-street-view"></i>',
iconSize: [0,0],
iconAnchor: [15,0],
className: 'StreetViewIcon'
});
var new_mark = L.marker();
function newMarker(e){
new_mark.setLatLng(e.latlng).addTo({{this._parent.get_name()}});
new_mark.setZIndexOffset(-1);
new_mark.setIcon(fontAwesomeIcon);
new_mark.on('dblclick', function(e){
{{this._parent.get_name()}}.removeLayer(e.target)})
var lat = e.latlng.lat.toFixed(4),
lng = e.latlng.lng.toFixed(4);
new_mark.bindPopup(
"<a href=https://www.google.com/maps?layer=c&cbll=" + lat + "," + lng + " target=blank><img src=img/streetview.svg width=70 title=StreetView class=StreetViewImage></img></a>",{
maxWidth: "auto",
className: 'StreetViewPopup'
});
};
{{this._parent.get_name()}}.on('click', newMarker); 
{% endmacro %}
""") # noqa

by defining a new constant based on the L.divIcon, which provides the lightweight icon for Leaflet markers using the div element instead of an image. By using the html option, we can simply paste the <i> content (Pic. 2) into our code.

Font Awesome paste the font

Pic. 2 Font awesome – The Icon type content needed for the interactive map purposes.

Next, we must use the .setIcon property for our marker in order to make it change. Finally, we should have a result such as this (Pic. 3):

Python folium font awesome icon too small

Pic. 3 The Font Awesome icon looks very small here.

and it’s still wrong, as our icon looks very small here. In this case, we have to increase the size of our icon. There are a few ways, but the simplest is providing the size inside the Font Awesome class as shown in the code below.

_template = Template(u"""
{% macro script(this, kwargs) %}
const fontAwesomeIcon = L.divIcon({
html: '<i class="fa-sharp fa-solid fa-3x fa-street-view"></i>',
iconSize: [0,0],
iconAnchor: [15,0],
className: 'StreetViewIcon'
});
var new_mark = L.marker();
function newMarker(e){
new_mark.setLatLng(e.latlng).addTo({{this._parent.get_name()}});
new_mark.setZIndexOffset(-1);
new_mark.setIcon(fontAwesomeIcon);
new_mark.on('dblclick', function(e){
{{this._parent.get_name()}}.removeLayer(e.target)})
var lat = e.latlng.lat.toFixed(4),
lng = e.latlng.lng.toFixed(4);
new_mark.bindPopup(
"<a href=https://www.google.com/maps?layer=c&cbll=" + lat + "," + lng + " target=blank><img src=img/streetview.svg width=70 title=StreetView class=StreetViewImage></img></a>",{
maxWidth: "auto",
className: 'StreetViewPopup'
})//.openPopup();
};
{{this._parent.get_name()}}.on('click', newMarker); 
{% endmacro %}
""") # noqa

Inside our class, we can provide something like fa-3x in order to increase the size of our marker three times (Pic. 4).

Python folium font awesome

Pic. 4 Icon multiplied by 3x is fine against the map.

Another option, which could be defined here is IconAnchor, where we can provide the correct offset against the mouse click. Don’t play much with the IconSize, because it doesn’t change your icon size! It creates an invisible box around the icon, which might fall too far from the place where the mouse was clicked.
Now, we can start customizing our icons from the CSS side. As you might have noticed, the className: ‘StreetViewIcon’ has been included for this purpose.
In this event, another macro inside the jinja2 Template is required. Our code will look as follows:

_template = Template(u"""
{% macro header(this, kwargs) %}
<style>
.StreetViewIcon{
color: green;
}
</style>
{% endmacro %}
{% macro script(this, kwargs) %}
const fontAwesomeIcon = L.divIcon({
html: '<i class="fa-sharp fa-solid fa-3x fa-street-view"></i>',
iconSize: [0,0],
iconAnchor: [15,0],
className: 'StreetViewIcon'
});
var new_mark = L.marker();
function newMarker(e){
new_mark.setLatLng(e.latlng).addTo({{this._parent.get_name()}});
new_mark.setZIndexOffset(-1);
new_mark.setIcon(fontAwesomeIcon);
new_mark.on('dblclick', function(e){
{{this._parent.get_name()}}.removeLayer(e.target)})
var lat = e.latlng.lat.toFixed(4),
lng = e.latlng.lng.toFixed(4);
new_mark.bindPopup(
"<a href=https://www.google.com/maps?layer=c&cbll=" + lat + "," + lng + " target=blank><img src=img/streetview.svg width=70 title=StreetView class=StreetViewImage></img></a>",{
maxWidth: "auto",
className: 'StreetViewPopup'
});
};
{{this._parent.get_name()}}.on('click', newMarker); 
{% endmacro %}
""") # noqa

and the result will be the green marker icon (Pic. 5).

Python folium on click marker customizing font awesome icon

Pic. 5 Our on-click marker icon is green now as per the styling defined.

Now is the time for styling the pop-up. For this purpose, we need to expand the <style> section in the macro and override some Leaflet built-in style features. Our final code will look as per below:

_template = Template(u"""
{% macro header(this, kwargs) %}
<style>
.StreetViewIcon{
color: green;
}
.StreetViewPopup .leaflet-popup-content-wrapper {
background-color: lightgreen;
color: green;
border-radius:15px;
height:48px;
width:70px;
}
.StreetViewPopup .leaflet-popup-content {
margin: auto;
display: block;
}
.StreetViewPopup .leaflet-popup-close-button {
color: green!important;
font-weight:bold!important;
}
.StreetViewPopup .leaflet-popup-tip {
border: 8px dashed green;
} 
</style>
{% endmacro %}
{% macro script(this, kwargs) %}
const fontAwesomeIcon = L.divIcon({
html: '<i class="fa-sharp fa-solid fa-3x fa-street-view"></i>',
iconSize: [0,0],
iconAnchor: [15,0],
className: 'StreetViewIcon'
});
var new_mark = L.marker();
function newMarker(e){
new_mark.setLatLng(e.latlng).addTo({{this._parent.get_name()}});
new_mark.setZIndexOffset(-1);
new_mark.setIcon(fontAwesomeIcon);
new_mark.on('dblclick', function(e){
{{this._parent.get_name()}}.removeLayer(e.target)})
var lat = e.latlng.lat.toFixed(4),
lng = e.latlng.lng.toFixed(4);
new_mark.bindPopup(
"<a href=https://www.google.com/maps?layer=c&cbll=" + lat + "," + lng + " target=blank><img src=img/streetview.svg width=70 title=StreetView class=StreetViewImage></img></a>",{
maxWidth: "auto",
className: 'StreetViewPopup'
});
};
{{this._parent.get_name()}}.on('click', newMarker); 
{% endmacro %}
""") # noqa

bringing our popup a nice look (Pic. 6). Before any built-in Leaflet CSS class we need to provide our own class, which will represent the individual features, as shown in the code above. Without providing our own marker class, all the changes will be applied to any other marker popups, which might not be necessarily desired.

Python folium styling on click marker popup

Pic. 6 The on-click Python Folium marker popup styling.

In conclusion, styling the on-click marker in Folium map can be a simple thing since you know how to use the jinja2 MacroElement.

Mariusz Krukar

 

Links:

  1. https://fontawesome.com/
  2. https://leafletjs.com/reference.html#marker
  3. https://docs.eegeo.com/eegeo.js/v0.1.780/docs/leaflet/L.Icon/
  4. https://docs.eegeo.com/eegeo.js/v0.1.830/docs/leaflet/L.DivIcon/

Forums:

  1. https://stackoverflow.com/questions/52136700/how-to-use-font-awesome-as-an-icon-in-leaflet-instead-of-marker
  2. https://stackoverflow.com/questions/49855062/using-leaflet-awesomemarkers-plugin-with-font-awesome-5
  3. https://stackoverflow.com/questions/23567203/leaflet-changing-marker-color
  4. https://stackoverflow.com/questions/31992235/how-do-i-decrease-the-size-of-a-font-awesome-icon
  5. https://stackoverflow.com/questions/18688630/increase-font-awesome-icons

 

 

 

You may also like...