How to embed a full-working (hover-effect) pygal chart (svg-string) inside streamlit?

I want to embed svg charts generated with PyGal ( https://www.pygal.org/) into my streamlit app.
I can do this using streamlite.image but the resulting svg graphic is not interactive, it is just a static image. The hover effect ( and the effect of clicking on legend to toggle data rows) is not working.
I tried to use the streamlit.components.v1.html component and it works, i get an interactive svg graphic with working hover effect…however, i only get the first ~200 pixels from top, then the rest of the svg graphic is empty. I tried putting the whole thing into an st.container with a given height, but no improvement.
I want the fully working svg graphic (with hover effect) displayed in streamlit in its full height. How can i do this ?

code:

import streamlit as st
import pygal  # install using pip install pygal
from streamlit.components.v1 import html
# create an svg using pygal
gauge_chart = pygal.Gauge(human_readable=True)
gauge_chart.title = f'speed in km/h'
gauge_chart.range = [0, 220]
gauge_chart.add('old car', 130)
gauge_chart.add("new car", 180)
gauge_chart.show_legend = True

st.html("<hr> without hover effect </hr>")
# put it into streamlit as static image (no hover effect)
st.image(gauge_chart.render(is_unicode=True), width=500)

# put it into streamlit as fully working svg with hover effect
def render_svg(svg_string):
    """Renders the given svg string."""
    c = st.container()
    with c:
        html(svg_string)

st.html("<hr> with hover effect (but only top ~200 pixels are visible) </hr>")
with st.container(height=800):
    render_svg(gauge_chart.render(is_unicode=True))

You have to set the height in the html element itself.

i find only a “viewbox” tag inside the svg-element produced by pygal. If i change it from 800x600 into 1600x1200 the resulting pygal chart is more visible ( circa 75%, but it is smaller).
Is the viewbox not compatible with a streamlit container ?

def render_svg(svg_string):
    """Renders the given svg string."""
    c = st.container(height=800)
    svg_string2 = svg_string.replace('viewBox="0 0 800 600"', 'viewBox="0 0 1600 1200"')
    with c:
        html(svg_string2)

I mean the height argument to st.components.v1.html.

1 Like

Thank you @Goyo now it works fantastic!!!

full working example:

import streamlit as st
import pygal  # install using pip install pygal
from streamlit.components.v1 import html
# create an svg using pygal
gauge_chart = pygal.Gauge(human_readable=True) #, height=400)
gauge_chart.title = f'speed in km/h'
gauge_chart.range = [0, 220]
gauge_chart.add('old car', 130)
gauge_chart.add("new car", 180)
gauge_chart.show_legend = True

st.html("<hr> without hover effect </hr>")
# put it into streamlit as static image (no hover effect)
st.image(gauge_chart.render(is_unicode=True)  , width=800) ## width argument is necessary here

# put it into streamlit as fully working svg with hover effect
def render_svg(svg_string):
    """Renders the given svg string."""
    c = st.container()
    with c:
        html(svg_string, height=600)  # <--- put the height in pixels here

st.html("<hr> with hover effect  </hr>")
with st.container():
    render_svg(gauge_chart.render(is_unicode=True))

#print(gauge_chart.render(is_unicode=True))

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.