Bokeh使用WebGL时,点击图例隐藏线条仅隐藏折线不隐藏散点
Bokeh 2.3.3 WebGL后端下同一图例关联图层点击隐藏不同步问题解决
问题描述
使用Bokeh 2.3.3版本,通过step(折线)和scatter(散点)渲染同一数据实现带标记点的折线图,开启WebGL后端优化大数据性能时,点击图例隐藏线条仅折线消失,散点仍显示。升级到2.4.3版本图表无法加载,升级到3.1.0版本因大量API变更导致代码无法运行。
原问题代码:
from bokeh.plotting import figure, show, Figure from bokeh.models import Legend x = [1, 2, 3, 4, 5] y = [6, 7, 2, 4, 5] p: Figure = figure(title="Simple line example", x_axis_label="x", y_axis_label="y", output_backend='webgl') p.add_layout(Legend(click_policy='hide'), 'right') p.step(x, y, name='rssi', legend_label='rssi', alpha=0.9, nonselection_alpha=0.5) line_alpha = 1.0 fill_alpha = 0.5 p.scatter(x, y, name='rssi', legend_label='rssi', marker='x', size=8, line_alpha=line_alpha, fill_alpha=fill_alpha, nonselection_line_alpha=line_alpha * 0.5, nonselection_fill_alpha=fill_alpha * 0.5) show(p)
问题原因
Bokeh 2.3.3的WebGL后端存在bug:当多个渲染器共享同一name或legend_label时,图例的hide点击策略仅能同步第一个关联渲染器的可见性,无法联动其他同组渲染器。
解决方案
通过自定义JS回调,监听折线渲染器的可见性变化,同步控制散点渲染器的显示状态,无需升级版本即可解决问题。修改后的代码如下:
from bokeh.plotting import figure, show, Figure from bokeh.models import Legend, LegendItem, CustomJS x = [1, 2, 3, 4, 5] y = [6, 7, 2, 4, 5] p: Figure = figure(title="Simple line example", x_axis_label="x", y_axis_label="y", output_backend='webgl') # 绘制折线和散点,保存渲染器引用 step_renderer = p.step(x, y, alpha=0.9, nonselection_alpha=0.5) scatter_renderer = p.scatter(x, y, marker='x', size=8, line_alpha=1.0, fill_alpha=0.5, nonselection_line_alpha=0.5, nonselection_fill_alpha=0.25) # 创建自定义图例项,关联折线渲染器 legend_item = LegendItem(label='rssi', renderers=[step_renderer]) legend = Legend(items=[legend_item], click_policy='hide') p.add_layout(legend, 'right') # 添加JS回调,同步散点渲染器的可见性与折线一致 sync_callback = CustomJS( args=dict(step_r=step_renderer, scatter_r=scatter_renderer), code=""" scatter_r.visible = step_r.visible; """ ) # 监听折线渲染器的可见性变化,触发同步 step_renderer.js_on_change('visible', sync_callback) show(p)
说明
- 该方案通过JS回调实现两个渲染器的可见性同步,不会影响WebGL的大数据渲染性能
- 避免了版本升级带来的兼容性问题,适配现有代码体系
内容的提问来源于stack exchange,提问作者quite68
相关产品推荐
相关产品推荐

