Plotly网格溢出Trace处理:Dash应用Indicator滚动显示问题
Dash应用Indicator网格滚动显示问题解决方案
我开发了一个Dash应用,用以下代码构建了一列Indicator网格:
indicators_ptf = go.Figure() indicators_ptf.layout.template = CHART_THEME indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = totalprolos, number = {'prefix': " $"}, title = {"text": "<br><span style='font-size:0.7em;color:gray'>Profit/Loss</span>"}, delta = {'position': "bottom", 'reference': totalprolos - portfolio_pct/100, 'relative': False, 'valueformat': ".2%"}, domain = {'row': 0, 'column': 0})) indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = availableCash, number = {'prefix': "$"}, title = {"text": "<br><span style='font-size:0.7em;color:gray'>Available Cash</span>"}, delta = {'position': "bottom", 'reference': 10000, 'relative': False}, domain = {'row': 1, 'column': 0})) indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = grandTotal, number = {'prefix': "$"}, title = {"text": "<span style='font-size:0.7em;color:gray'>Total Value</span>"}, delta = {'position': "bottom", 'reference': 10000, 'relative': False}, domain = {'row': 2, 'column': 0})) row_n=3 for stock in stocks: indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = stock['prolos'], number = {'prefix': "$"}, title = {"text": stock['symbol']}, delta = {'position': "bottom", 'reference': stock['prolos'] - stock['perc_change']/100, 'relative': False, 'valueformat': ".2%"}, domain = {'row': row_n, 'column': 0})) row_n += 1 indicators_ptf.update_layout( grid = {'rows': 5, 'columns': 1, 'pattern': "independent"}, margin=dict(l=50, r=50, t=30, b=30) )
问题描述
当投资组合中的股票数量超过2只时,新增的股票Indicator会覆盖其他行的内容。我希望META及后续股票Indicator能被隐藏在下方,支持滚动查看。尝试过fig.update_traces(colorbar_ticklabeloverflow=...)和fig.update_yaxes(ticklabeloverflow=...)但无效果。我的Dash布局代码如下:
dash_app.layout = dbc.Container( [ dbc.Row(dbc.Col(html.H2('PORTFOLIO OVERVIEW', className='text-center text-primary, mb-3'))), # 标题行 dbc.Row([ # 第二行开始 dbc.Col([ # 第二行第一列 html.H5('Total Portfolio Value ($USD)', className='text-center'), dcc.Graph(id='chrt-portfolio-main', figure=chart_ptfvalue, style={'height':550}), html.Hr(), ], width={'size': 8, 'offset': 0, 'order': 1}), # 第二行第一列宽度 dbc.Col([ # 第二行第二列 html.H5('Portfolio', className='text-center'), dcc.Graph(id='indicators-ptf', figure=indicators_ptf, style={'height':550, 'overflowY': 'scroll', 'maxHeight': '550px'}), html.Hr() ], width={'size': 2, 'offset': 0, 'order': 2}), # 第二行第二列宽度 dbc.Col([ # 第二行第三列 html.H5('S&P500', className='text-center'), dcc.Graph(id='indicators-sp', figure=indicators_sp500, style={'height':550}), html.Hr() ], width={'size': 2, 'offset': 0, 'order': 3}), # 第二行第三列宽度 ]), # 第二行结束 dbc.Row([ # 第三行开始 dbc.Col([ # 第三行第一列 html.H5('Monthly Return (%)', className='text-center'), dcc.Graph(id='chrt-portfolio-secondary', figure=fig_growth2, style={'height':380}), ], width={'size': 8, 'offset': 0, 'order': 1}), # 第三行第一列宽度 dbc.Col([ # 第三行第二列 html.H5('Top 15 Holdings', className='text-center'), dcc.Graph(id='pie-top15', figure = donut_top, style={'height':380}), ], width={'size': 4, 'offset': 0, 'order': 2}), # 第三行第二列宽度 ]) # 第三行结束 ], fluid=True)
问题原因及修复方案
核心问题:
- 固定设置
grid={'rows':5},当股票数量超过2只时,总Indicator数量超过5,Plotly会强制压缩所有元素到5行内,导致重叠。 dcc.Graph是Canvas渲染组件,直接给它加overflowY样式无法作用于内部图表内容。
- 固定设置
具体修复步骤:
- 动态设置网格行数:根据实际Indicator总数(固定3个+股票数量)设置
grid.rows,避免固定行数限制。 - 用HTML容器包裹图表实现滚动:将
dcc.Graph放入html.Div容器,给容器设置滚动样式,让图表内容超出容器高度时显示滚动条。
- 动态设置网格行数:根据实际Indicator总数(固定3个+股票数量)设置
修改后的Indicator构建代码
indicators_ptf = go.Figure() indicators_ptf.layout.template = CHART_THEME indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = totalprolos, number = {'prefix': " $"}, title = {"text": "<br><span style='font-size:0.7em;color:gray'>Profit/Loss</span>"}, delta = {'position': "bottom", 'reference': totalprolos - portfolio_pct/100, 'relative': False, 'valueformat': ".2%"}, domain = {'row': 0, 'column': 0})) indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = availableCash, number = {'prefix': "$"}, title = {"text": "<br><span style='font-size:0.7em;color:gray'>Available Cash</span>"}, delta = {'position': "bottom", 'reference': 10000, 'relative': False}, domain = {'row': 1, 'column': 0})) indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = grandTotal, number = {'prefix': "$"}, title = {"text": "<span style='font-size:0.7em;color:gray'>Total Value</span>"}, delta = {'position': "bottom", 'reference': 10000, 'relative': False}, domain = {'row': 2, 'column': 0})) row_n=3 for stock in stocks: indicators_ptf.add_trace(go.Indicator( mode = "number+delta", value = stock['prolos'], number = {'prefix': "$"}, title = {"text": stock['symbol']}, delta = {'position': "bottom", 'reference': stock['prolos'] - stock['perc_change']/100, 'relative': False, 'valueformat': ".2%"}, domain = {'row': row_n, 'column': 0})) row_n += 1 # 动态计算总行数:固定3个指标 + 股票数量 total_rows = 3 + len(stocks) indicators_ptf.update_layout( grid = {'rows': total_rows, 'columns': 1, 'pattern': "independent"}, margin=dict(l=50, r=50, t=30, b=30) )
修改后的布局代码
dash_app.layout = dbc.Container( [ dbc.Row(dbc.Col(html.H2('PORTFOLIO OVERVIEW', className='text-center text-primary, mb-3'))), # 标题行 dbc.Row([ # 第二行开始 dbc.Col([ # 第二行第一列 html.H5('Total Portfolio Value ($USD)', className='text-center'), dcc.Graph(id='chrt-portfolio-main', figure=chart_ptfvalue, style={'height':550}), html.Hr(), ], width={'size': 8, 'offset': 0, 'order': 1}), # 第二行第一列宽度 dbc.Col([ # 第二行第二列 html.H5('Portfolio', className='text-center'), # 用Div包裹Graph,设置滚动容器 html.Div( dcc.Graph(id='indicators-ptf', figure=indicators_ptf, style={'height': '100%'}), style={'height': 550, 'overflowY': 'auto'} ), html.Hr() ], width={'size': 2, 'offset': 0, 'order': 2}), # 第二行第二列宽度 dbc.Col([ # 第二行第三列 html.H5('S&P500', className='text-center'), dcc.Graph(id='indicators-sp', figure=indicators_sp500, style={'height':550}), html.Hr() ], width={'size': 2, 'offset': 0, 'order': 3}), # 第二行第三列宽度 ]), # 第二行结束 dbc.Row([ # 第三行开始 dbc.Col([ # 第三行第一列 html.H5('Monthly Return (%)', className='text-center'), dcc.Graph(id='chrt-portfolio-secondary', figure=fig_growth2, style={'height':380}), ], width={'size': 8, 'offset': 0, 'order': 1}), # 第三行第一列宽度 dbc.Col([ # 第三行第二列 html.H5('Top 15 Holdings', className='text-center'), dcc.Graph(id='pie-top15', figure = donut_top, style={'height':380}), ], width={'size': 4, 'offset': 0, 'order': 2}), # 第三行第二列宽度 ]) # 第三行结束 ], fluid=True)
- 额外说明:
- 动态设置
grid.rows确保每个Indicator都有独立的行空间,不会出现重叠。 - 容器的
overflowY: auto会在内容高度超过容器时自动显示垂直滚动条,实现滚动查看所有Indicator。 - 将Graph的高度设为
100%,让它完全填满容器,滚动体验更流畅。
- 动态设置
内容的提问来源于stack exchange,提问作者Oris
相关产品推荐
相关产品推荐

