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

Bokeh CustomJS实现Jupyter交互式散点图无更新问题求助

问题修复与Bokeh交互式核心要点

你的代码存在两个关键问题导致滑块拖动后图表无更新,以下是修复方案及核心知识点:

代码修复

错误原因

  1. 滑块值获取错误:你将f1和f2都赋值为cb_obj.value,但cb_obj仅代表当前触发事件的滑块(比如拖动slider1时,cb_obj就是slider1),这会导致两个变量取同一个滑块的值,无法正确获取另一个滑块的当前值。
  2. 未显式触发数据源更新:虽然重新赋值source.data理论上会触发更新,但部分场景下需要显式通知Bokeh数据源已变化。

修复后的代码

from bokeh.models import ColumnDataSource, Slider, CustomJS
from bokeh.plotting import figure, show
from bokeh.layouts import column

source = ColumnDataSource(data=dict(x=[1,0,1], y=[0,1,1]))

plot = figure(width=400, height=400)
plot.circle('x', 'y', source=source, line_width=3, line_alpha=0.6)

slider1 = Slider(start=0.1, end=6, value=1, step=.1, title="Escalar 1")
slider2 = Slider(start=0.1, end=6, value=1, step=.1, title="Escalar 2")

update_tamanho = CustomJS(args=dict(source=source, slider1=slider1, slider2=slider2), code="""
// 直接从传入的滑块对象获取当前值,不依赖cb_obj
const f1 = slider1.value;
const f2 = slider2.value;
const x = source.data.x;
const y = source.data.y;

// 修改指定点的坐标
x[0] = f1;
x[2] = f1;
y[1] = f2;
y[2] = f2;

// 显式通知Bokeh数据源更新,触发图表重绘
source.change.emit();
""")

slider2.js_on_change('value', update_tamanho)
slider1.js_on_change('value', update_tamanho)

show(column(slider1, slider2, plot))

Bokeh交互式图表核心要点

  • ColumnDataSource是交互核心:所有可交互的图表元素都要绑定到ColumnDataSource,它是Python与JS端数据同步的桥梁,修改数据源即可联动更新图表。
  • CustomJS的参数与cb_obj:
    • args用于将Python端的对象(数据源、控件等)传递到JS代码,在JS中可直接访问对象属性(如value)。
    • cb_obj仅代表当前触发事件的控件,适合单个控件控制单一参数的场景,多控件联动时直接从传入的控件对象取值更可靠。
  • 事件绑定规则:
    • 纯前端交互用js_on_change绑定CustomJS,无需后端,适合Jupyter Notebook静态展示。
    • 需要后端逻辑处理时,用on_change绑定Python回调,但必须启动Bokeh服务器。
  • JS端数据源更新:修改数据源数组后,需调用source.change.emit()显式触发更新;优先修改数组元素而非替换整个数组,性能更优。
  • 两种交互模式:
    • 纯前端模式:适合简单交互,无需服务器,静态页面即可运行。
    • 后端模式(Bokeh Server):支持复杂Python逻辑处理,实现双向实时数据同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 22:55:25