如何在Bokeh中通过回调实现x轴范围变化时调整y轴范围?
问题描述
我希望每次x轴范围变化时,更改y轴的可见范围。但当前代码似乎无法正常工作:平移或修改x轴范围时,回调函数未被触发,或是回调函数存在问题?
现有代码
import numpy as np from bokeh.plotting import figure, show from bokeh.models import CustomJS x = list(range(100)) y = list(np.random.randint(-10, 10, 100)) y = np.cumsum(y) p1 = figure(title="Random", width=600, height=600) p1.line(x, y, color="red") callback = CustomJS(args=dict(yrange=p1.y_range), code=""" yrange.start=-10; yrange.end=10;""") p1.x_range.js_on_change("end", callback) show(p1)
问题原因与解决方法
核心问题
你只监听了x_range的end属性变化,但平移或缩放x轴时,start和end会同时更新,只监听单个属性会导致部分操作无法触发回调。以下分两种场景给出解决方案:
场景1:固定y轴范围为-10到10
同时监听x_range的start和end属性,确保任何x轴范围修改都能触发回调:
import numpy as np from bokeh.plotting import figure, show from bokeh.models import CustomJS x = list(range(100)) y = list(np.random.randint(-10, 10, 100)) y = np.cumsum(y) p1 = figure(title="Random", width=600, height=600) p1.line(x, y, color="red") callback = CustomJS(args=dict(yrange=p1.y_range), code=""" yrange.start = -10; yrange.end = 10; """) # 同时监听start和end的变化 p1.x_range.js_on_change("start", callback) p1.x_range.js_on_change("end", callback) show(p1)
场景2:根据当前x轴范围内的y值动态调整y轴范围
如果需要自动适配当前x区间内的y值极值,需要将x、y数据传入JS回调,在前端筛选并计算范围:
import numpy as np from bokeh.plotting import figure, show from bokeh.models import CustomJS x = list(range(100)) y = list(np.random.randint(-10, 10, 100)) y = np.cumsum(y) p1 = figure(title="Random", width=600, height=600) p1.line(x, y, color="red") # 传入x、y数组供JS回调使用 callback = CustomJS(args=dict(yrange=p1.y_range, x=x, y=y), code=""" const xStart = cb_obj.start; const xEnd = cb_obj.end; // 筛选当前x范围内的y值 const filteredY = y.filter((_, idx) => x[idx] >= xStart && x[idx] <= xEnd); if (filteredY.length > 0) { const minY = Math.min(...filteredY); const maxY = Math.max(...filteredY); // 添加少量边距避免图形紧贴轴边界 yrange.start = minY - 1; yrange.end = maxY + 1; } """) # 监听x_range的所有范围变化 p1.x_range.js_on_change("start", callback) p1.x_range.js_on_change("end", callback) show(p1)
关键说明
- Bokeh中
x_range的范围变化会同时修改start和end属性,仅监听其中一个会导致回调触发不完整。 - 动态计算y轴范围时,必须将原始x、y数据传递给JS回调,才能在前端完成数据筛选和极值计算。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

