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
相关产品推荐
相关产品推荐

