如何动态调整Bokeh图表中segment线段的线宽
实现方案
不需要重写整个图表,也无需删除原有segment再重新添加,你已经创建的high_low_segment对象可以直接修改line_width属性,根据你使用场景不同有两种实现路径:
1. Bokeh Server 场景(纯Python实现)
如果你是用bokeh serve运行的交互式服务,直接在Python侧绑定RangesUpdate事件回调即可:
from bokeh.events import RangesUpdate # 定义回调函数 def adjust_line_width(event): # 获取当前x轴的时间范围差(单位:毫秒,适配datetime类型的x轴) x_range = p.x_range range_span = x_range.end - x_range.start # 自定义线宽映射规则,示例规则:放大程度越高、范围越小,线越宽 if range_span < 7 * 24 * 3600 * 1000: # 显示范围小于7天 high_low_segment.glyph.line_width = 3 elif range_span < 30 * 24 * 3600 * 1000: # 显示范围小于30天 high_low_segment.glyph.line_width = 2 else: high_low_segment.glyph.line_width = 1 # 绑定范围更新事件到图表 p.on_event(RangesUpdate, adjust_line_width)
2. 静态HTML输出场景(需少量JS代码)
如果你是直接输出HTML文件离线使用,不需要启动Bokeh Server,就需要用CustomJS绑定回调:
from bokeh.models import CustomJS callback = CustomJS(args=dict(segment_glyph=high_low_segment.glyph, x_range=p.x_range), code=""" // 获取当前x轴范围差 const range_span = x_range.end - x_range.start // 线宽映射规则和Python侧逻辑一致,时间单位为毫秒 if (range_span < 7 * 24 * 3600 * 1000) { segment_glyph.line_width = 3 } else if (range_span < 30 * 24 * 3600 * 1000) { segment_glyph.line_width = 2 } else { segment_glyph.line_width = 1 } """) # 绑定回调到x轴范围变化事件 p.x_range.js_on_change('start', callback) p.x_range.js_on_change('end', callback)
注意事项
- 自定义线宽映射规则时,要注意datetime类型的x轴数值单位是unix时间戳毫秒,计算范围差的时候要对应单位
- 直接修改glyph的属性就会实时渲染,不需要额外调用刷新或者重建图表的方法
内容的提问来源于stack exchange,提问作者Pierre Mardon
相关产品推荐
相关产品推荐

