You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask+Bootstrap4+Bokeh仪表盘响应式设计异常求助

解决Bokeh图表在隐藏标签页中失去响应式的问题

这个问题的核心原因是:Bokeh图表初始化时,如果所在的容器处于隐藏状态(比如display: none),它无法正确计算容器的尺寸,会使用默认尺寸渲染;当你切换回原标签页时,Bokeh也不会自动重新检测容器尺寸变化。结合你的代码,我整理了几个针对性的解决方案:

1. 修正Bokeh图表的sizing_mode设置

首先看你的绘图代码里,当前设置的是sizing_mode="scale_width",但你提到想让图表同时适配宽高,应该改成sizing_mode="stretch_both"(注意是下划线分隔,Bokeh的参数命名规范):

p = figure(
    plot_height=320, 
    x_axis_type="datetime", 
    y_range=(26, 60),
    tools=tools, 
    sizing_mode="stretch_both"  # 替换原来的scale_width
)

这个参数会让图表自动拉伸以填满父容器的宽高,是实现响应式的关键。

2. 监听标签页切换事件,手动触发Bokeh尺寸更新

因为隐藏容器显示时,Bokeh不会主动感知尺寸变化,所以需要在标签页切换完成后,手动调用Bokeh的尺寸重置方法。根据你用的accordion面板结构,添加以下JavaScript代码:

// 监听折叠面板的点击事件
$('.accordion').on('click', function() {
    // 延迟100ms,确保面板已经展开、DOM尺寸更新完成
    setTimeout(function() {
        // 遍历所有Bokeh文档,触发尺寸重置
        Bokeh.documents.forEach(doc => doc.resize());
    }, 100);
});

如果是用Bootstrap的官方标签页组件(nav-tabs),可以改用shown.bs.tab事件:

$('a[data-toggle="tab"]').on('shown.bs.tab', function() {
    setTimeout(function() {
        Bokeh.documents.forEach(doc => doc.resize());
    }, 100);
});

这段代码会在标签页完全显示后,强制Bokeh重新计算每个图表的容器尺寸,恢复响应式效果。

3. 优化容器CSS设置,确保尺寸计算准确

你的.fixed_height类已经设置了固定高度,建议再给图表容器添加position: relative,帮助Bokeh更准确地获取容器边界:

.fixed_height{
    height:380px;
    padding-bottom: 30px;
    margin-bottom: 50px;
    position: relative; /* 添加这行 */
}
.x_panel {
    overflow: hidden; /* 确保超出部分被裁剪 */
}

4. 改用更灵活的Bokeh嵌入方式(可选)

你当前用file_html生成完整的HTML字符串嵌入,这种方式灵活性较低。推荐改用components方法拆分脚本和DOM元素,让嵌入更可控:

修改Python绘图函数

from bokeh.embed import components  # 导入components

def plottingto(dataframe, lineID, plotnametext ):
    # ... 数据源、工具配置代码不变 ...
    p = figure(
        plot_height=320, 
        x_axis_type="datetime", 
        y_range=(26, 60),
        tools=tools, 
        sizing_mode="stretch_both"
    )
    # ... 绘图代码不变 ...
    # 替换file_html,返回脚本和div
    script, div = components(p, CDN)
    return script, div

在Flask视图中传递参数

# 假设你原来的视图函数
@app.route('/dashboard')
def dashboard():
    # 获取数据...
    script_week_to, div_week_to = plottingto(week_data, lineID, "Hinweg Woche")
    script_week_back, div_week_back = plottingto(week_data_back, lineID, "Rückweg Woche")
    return render_template('dashboard.html', 
                           BOKEH_SCRIPT_TO=script_week_to,
                           BOKEH_DIV_TO=div_week_to,
                           BOKEH_SCRIPT_BACK=script_week_back,
                           BOKEH_DIV_BACK=div_week_back)

在HTML模板中嵌入

<div class="x_panel tile fixed_height overflow_hidden">
    {{ BOKEH_DIV_TO | safe }}
</div>
<!-- 页面底部统一加载Bokeh核心脚本和图表脚本 -->
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
{{ BOKEH_SCRIPT_TO | safe }}
{{ BOKEH_SCRIPT_BACK | safe }}

这种方式让Bokeh的初始化逻辑更清晰,也更容易配合JS事件监听。

调试小技巧

如果切换后图表还是有问题,可以打开浏览器控制台(F12),手动执行Bokeh.documents[0].resize(),如果图表恢复正常,说明是事件监听的时机问题,调整setTimeout的延迟时间即可。

内容的提问来源于stack exchange,提问作者Lars

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:05:47