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

Bokeh技术问题:热力图中HoverTool无法反映CDSView筛选结果

解决Bokeh切换CDSView后HoverTool不同步的问题

这个问题我之前也碰到过!本质是HoverTool默认没关联到使用CDSView的渲染器,导致它还是读取原始全量数据源的信息。给你两种靠谱的解决思路:

方法1:动态切换渲染器并关联HoverTool

这种方式适合需要为不同TYPE保留独立样式的场景,核心是给每个TYPE创建一个绑定对应CDSView的渲染器,再通过单选按钮切换渲染器的可见性,同时让HoverTool只监听当前激活的渲染器:

# 先创建对应TYPE的渲染器,初始只显示A类型
renderer_a = p_heat.rect(
    x='MONTH', y='YEAR', width=1, height=1,
    source=heat_source, view=A_view,
    fill_color=LinearColorMapper(palette="Viridis256", low=0, high=10)
)
renderer_b = p_heat.rect(
    x='MONTH', y='YEAR', width=1, height=1,
    source=heat_source, view=B_view,
    fill_color=LinearColorMapper(palette="Viridis256", low=0, high=10)
)
renderer_b.visible = False  # 初始隐藏B类型

# 创建HoverTool,只监听初始的A渲染器
hover = HoverTool(
    tooltips=[
        ('月份', '@MONTH'),
        ('年份', '@YEAR'),
        ('数量', '@COUNT')
    ],
    renderers=[renderer_a]
)
p_heat.add_tools(hover)

# 绑定单选按钮的回调,切换渲染器可见性和HoverTool监听目标
radio = RadioButtonGroup(labels=['类型A', '类型B'], active=0)
callback = CustomJS(
    args=dict(renderer_a=renderer_a, renderer_b=renderer_b, hover=hover),
    code="""
        renderer_a.visible = (cb_obj.active === 0);
        renderer_b.visible = (cb_obj.active === 1);
        // 更新HoverTool的监听渲染器
        hover.renderers = cb_obj.active === 0 ? [renderer_a] : [renderer_b];
    """
)
radio.js_on_change('active', callback)

方法2:动态更新单个渲染器的CDSView(更简洁)

如果所有TYPE的热力图样式一致,只需要维护一个渲染器,动态切换它的view属性即可,HoverTool因为绑定了这个渲染器,会自动跟随视图过滤:

# 创建单个渲染器,初始使用A类型的视图
renderer = p_heat.rect(
    x='MONTH', y='YEAR', width=1, height=1,
    source=heat_source, view=A_view,
    fill_color=LinearColorMapper(palette="Viridis256", low=0, high=10)
)

# 创建HoverTool并绑定到这个渲染器
hover = HoverTool(
    tooltips=[
        ('月份', '@MONTH'),
        ('年份', '@YEAR'),
        ('数量', '@COUNT')
    ],
    renderers=[renderer]
)
p_heat.add_tools(hover)

# 单选按钮回调更新渲染器的视图
radio = RadioButtonGroup(labels=['类型A', '类型B'], active=0)
callback = CustomJS(
    args=dict(renderer=renderer, view_a=A_view, view_b=B_view),
    code="""
        // 切换渲染器的CDSView
        renderer.view = cb_obj.active === 0 ? view_a : view_b;
    """
)
radio.js_on_change('active', callback)

关键注意点

  • 一定要通过renderers参数把HoverTool绑定到渲染器上,而不是直接绑定数据源,这样HoverTool只会响应渲染器上的可见元素(也就是CDSView过滤后的内容)。
  • 如果是在Bokeh Server环境下使用,不需要用CustomJS,直接在Python回调函数里修改渲染器的view或可见性即可,逻辑是一样的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:02:11