本地Streamlit应用中Plotly仪表盘图表异常渲染问题
解决Streamlit中Plotly仪表盘图表残留渲染问题
问题现象
- 本地部署的Streamlit应用里,勾选「MTR」复选框切换到仪表盘页面后,取消勾选返回默认页面时,本该无图表的区域会出现3个透明的仪表盘图表。
- 图表呈非预期的透明状态,属于页面切换后的组件渲染残留问题。
复现代码
import streamlit as st import plotly.graph_objects as go st.set_page_config(page_title='example', layout='wide') colcheck1, colcheck2, colcheck3 = st.columns([1,1,4]) with colcheck1: mt = st.checkbox('MT') with colcheck2: mtr = st.checkbox('MTR') def mtr_page(): col1, col2 = st.columns([3,10]) with col1: fig = gauge_3() st.plotly_chart(fig) fig = gauge_3() st.plotly_chart(fig) def gauge_creation(fig, value,title,domain): if value >= 90: color = 'green' elif value >=60: color = 'yellow' else: color = 'red' fig.add_trace(go.Indicator( mode='gauge+number', value = value, title=title, domain=domain, number={'suffix':'%'}, gauge={ 'axis':{'range':[0,100],'tickwidth':1, 'showticklabels':False}, 'bar': {'color':color}, 'borderwidth':1 } )) return fig def gauge_3(): fig = go.Figure() gauge_creation(fig,92,'30day',{'row':0, 'column':1}) gauge_creation(fig,92,'90day',{'row':0, 'column':2}) gauge_creation(fig,92,'1year',{'row':0, 'column':3}) fig.add_annotation(dict(font=dict(color='white',size=15), x=0, y=.12, showarrow=False, text='Name', xref='paper', yref='paper')) fig.update_layout( grid = {'rows':1, 'columns':4, 'pattern':'independent'}, width = 500, height = 100, margin = {'t':50, 'b':10, 'r':26, 'l': 18} ) return fig def test_blank(): col1, col2 = st.columns([1,2]) with col1: st.write('hi') if mtr == False and mt == False: test_blank() if mtr: mtr_page()
原因分析
Streamlit动态切换页面内容时,对于Plotly这类第三方图表组件的DOM元素回收存在不完全的情况。尤其是使用st.columns嵌套渲染图表时,旧组件的状态没有被彻底重置,导致切换回空白页面后,残留的透明图表DOM没有被清理。
解决方案
方法1:用会话状态精准控制页面渲染
通过st.session_state跟踪页面状态,确保切换时强制刷新内容,避免旧组件残留:
import streamlit as st import plotly.graph_objects as go st.set_page_config(page_title='example', layout='wide') # 初始化会话状态,记录当前页面 if 'current_page' not in st.session_state: st.session_state.current_page = 'blank' colcheck1, colcheck2, colcheck3 = st.columns([1,1,4]) with colcheck1: mt = st.checkbox('MT', on_change=lambda: st.session_state.update(current_page='mt' if mt else 'blank')) with colcheck2: mtr = st.checkbox('MTR', on_change=lambda: st.session_state.update(current_page='mtr' if mtr else 'blank')) # 原函数gauge_creation、gauge_3、mtr_page、test_blank保持不变 # 根据会话状态渲染对应页面 match st.session_state.current_page: case 'blank': test_blank() case 'mtr': mtr_page()
方法2:用占位符动态替换页面内容
使用st.empty()创建全局内容容器,切换页面时用新内容完全覆盖旧内容,确保旧图表被彻底移除:
import streamlit as st import plotly.graph_objects as go st.set_page_config(page_title='example', layout='wide') # 创建全局内容占位符 content_container = st.empty() colcheck1, colcheck2, colcheck3 = st.columns([1,1,4]) with colcheck1: mt = st.checkbox('MT') with colcheck2: mtr = st.checkbox('MTR') def mtr_page(): with content_container.container(): col1, col2 = st.columns([3,10]) with col1: fig = gauge_3() st.plotly_chart(fig) fig = gauge_3() st.plotly_chart(fig) def test_blank(): with content_container.container(): col1, col2 = st.columns([1,2]) with col1: st.write('hi') # 原函数gauge_creation、gauge_3保持不变 # 页面渲染逻辑 if mtr: mtr_page() elif not mt and not mtr: test_blank()
方法3:优化Plotly图表布局配置
修改图表的背景色设置,避免透明残留问题,同时确保布局尺寸匹配容器:
def gauge_3(): fig = go.Figure() gauge_creation(fig,92,'30day',{'row':0, 'column':1}) gauge_creation(fig,92,'90day',{'row':0, 'column':2}) gauge_creation(fig,92,'1year',{'row':0, 'column':3}) fig.add_annotation(dict(font=dict(color='white',size=15), x=0, y=.12, showarrow=False, text='Name', xref='paper', yref='paper')) fig.update_layout( grid = {'rows':1, 'columns':4, 'pattern':'independent'}, width = 500, height = 100, margin = {'t':50, 'b':10, 'r':26, 'l': 18}, # 设置背景色与页面一致,避免透明残留 paper_bgcolor=st.get_option('theme.backgroundColor'), plot_bgcolor=st.get_option('theme.backgroundColor') ) return fig
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

