Nach
Nach

Reputation: 11

Displaying image on Folium Marker pop-up

I'm trying to get a .svg file (image.svg) to show up on my folium marker pop-up but all I'm getting is a white pop-up box with nothing in it. This .svg file is in the same directory as my .py file, please help, my .py is below:

import pandas
import os
import folium
from folium import IFrame

map = folium.Map(location=[38.58, -99.09], zoom_start=6, tiles="Stamen Terrain")

svg = """
<svg width="400" height="400"
  <img src="image.svg"/>
</svg>
"""

iframe = IFrame(svg, width=400, height=400)
popup = folium.Popup(iframe, max_width=1000)
icon = folium.Icon(color="red", icon="ok")
marker = folium.Marker(location=[38.58, -99.09], popup=popup, icon=icon)
marker.add_to(map)

map.save(outfile='TestMap.html')

Upvotes: 1

Views: 5594

Answers (2)

vine_J
vine_J

Reputation: 153

I tried InLaw's above method for image and it worked for me. With some more research I was able to add image along with HTML content together into the popup.

Create map

m = folium.Map(location=[53.350496, -6.239456], zoom_start=7, tiles='stamentoner')

For each datapoint, I inserted one single image:

for i in range(0,len(data)):
  file =  'some-image-file.jpg'
  dir_base = os.getcwd()
  Filename = dir_base + "/" + file

  encoded = base64.b64encode(open(Filename, 'rb').read())

  svg = """
  <object data="data:image/jpg;base64,{}" width="{}" height="{} type="image/svg+xml">
  </object>""".format

You can change these attributes as per your image requirements

  width, height, fat_wh = 300, 300, 1.3

Adding this to the iframe:

  iframe = IFrame(svg(encoded.decode('UTF-8'), width, height) , width=width*fat_wh, height=height*fat_wh)

Adding iframe to popup:

  popup  = folium.Popup(iframe, parse_html = True, max_width=1500)

Adding popup to Marker and Marker to map m :

  folium.Marker([data.iloc[i]['lon'], data.iloc[i]['lat']],  icon=folium.Icon(color='brown', icon='anchor', prefix='fa'), 
                popup=popup).add_to(m)

enter image description here

Now, if you also want to add some text via HTML next to your image in the popup, then instead of directly passing SVG into IFrame, you can add it to your html, something like this:

html = My_htmlStuff
html = html + svg(encoded.decode('UTF-8'), width, height)

And then add your html to the iFrame:

iframe = IFrame(html=html , width=width*fat_wh, height=height*fat_wh)
  popup  = folium.Popup(iframe, parse_html = True)

enter image description here

Upvotes: 2

InLaw
InLaw

Reputation: 2697

like you can see at "add img to popup", you cannot point to a path like in JavaScript but need to encode it first:

import os 
import folium
print( folium.__version__)

from folium import IFrame
from folium.plugins import FloatImage

import numpy as np
import branca

import base64
import matplotlib.pyplot as plt


lon_ct = 50
fkt=10
num = 60
m = folium.Map((lon_ct , 6), tiles='stamentoner', zoom_start=5 )


lats = (lon_ct * np.cos(np.linspace(0, 2*np.pi, num))/fkt ) + lon_ct
lons = (lon_ct * np.sin(np.linspace(0, 2*np.pi, num))/fkt ) + 10
colors = np.sin(5 *    np.linspace(0, 2*np.pi, num))

lgd_txt = '<span style="color: {col};">{txt}</span>'

for idx, color in enumerate( ['red', 'blue']):  # color choice is limited
    print(color)
    fg = folium.FeatureGroup(name= lgd_txt.format( txt= color+' egg', col= color))
    pl = folium.features.PolyLine(
            list(zip(lats, lons - idx*fkt)),
            color=color,            
            weight=10, )
    fg.add_child(pl)
    m.add_child( fg)

folium.vector_layers.Marker(location=[50.82416, -0.1265],popup = 'Londonary', 
                  icon= folium.Icon(color='gray', icon_color='yellow',icon = 'fire')
                           ).add_to(m) 

try:    
    ## # add img to popup
    file =  'milan2.png'
    dir_base = os.getcwd()
    Filename = dir_base + file

    encoded = base64.b64encode(open(Filename, 'rb').read())
    svg = """
    <object data="data:image/png;base64,{}" width="{}" height="{} type="image/svg+xml">
    </object>""".format
    width, height, fat_wh = 78, 78, 1.25
    iframe = IFrame(svg(encoded.decode('UTF-8'), width, height) , width=width*fat_wh, height=height*fat_wh)
    popup  = folium.Popup(iframe, max_width=2650)

    folium.vector_layers.Marker(location=[45.464, 9.1915],popup = popup, 
                                icon= folium.Icon(color='beige', icon_color='yellow',icon = 'globe')
                                ).add_to(m) 
except (FileNotFoundError, NameError) as error:    
    print( "no dir given .. ")

folium.vector_layers.Marker(location=[48.86098, 2.33589],popup = 'France',
                            icon= folium.Icon(color='green', icon_color='orange',icon = 'unchecked')).add_to(m)

folium.map.LayerControl('topleft', collapsed= False).add_to(m)

#Set the zoom to the maximum possible
m.fit_bounds( m.get_bounds())



block_txt = """    
    <span style="
    display: block;
    float: left;
    height: 16px;
    width: 30px;
    margin-right: 5px;
    margin-left: 0;
    border: 1px solid #999;

    background:{col};opacity:0.99
    <!--  -->
    ">
    {item}
    </span> 
    """
marker_txt_mk  = """<br> &nbsp; <span style="color: {col};">{item}</span> &nbsp; <i class="fa fa-repeat fa-2x" style="color:{col}"></i> </li>"""
# https://fontawesome.com/icons?d=gallery&m=free
marker_txt_rep = """<br> &nbsp; <span style="color: {col};">{item}</span> &nbsp; <i class="glyphicon glyphicon-repeat" style="color:{col}"></i> </li>"""
marker_txt_be  = """<br> &nbsp; <span style="color: {col};">{item}</span> &nbsp; <i class="glyphicon glyphicon-tree-deciduous fa-2x" style="color:{col}"></i> </li>"""
# https://getbootstrap.com/docs/3.3/components/#glyphicons

html_itms = marker_txt_rep.format( item= "egg red" , col= "red") \
            + marker_txt_mk.format( item= "egg blue" , col= "blue") \
            + marker_txt_be.format( item= "mark green" , col= "green") \

legend_html = """
     <div style="
     position: fixed; 
     top: 114px; left: 119px; width: 15x; height: 110x; 
     border:1px solid grey; 
     border-radius: 5px;
     z-index:9999; 

     background-color:white;     opacity: .99;
     <!-- background-color:rgba(255, 255, 255, 0.99); -->
     border-radius:6px;

     font-size:13px;
     font-weight: bold;

     ">
     &nbsp; {title} 

     {itm_txt}
     </ul>
     </div> """.format( title = "Legend html", itm_txt= html_itms)
m.get_root().html.add_child(folium.Element( legend_html ))

m

result: enter image description here

Upvotes: 2

Related Questions