如何使用 Bokeh 从 Python 调用 JavaScript 函数?
How can I call a JavaScript function from Python using Bokeh?
我有这种情况:
- 我有一些数据(在 pandas 数据框中)用于绘制图表
- 当我按下按钮(由散景小部件构建)时,我可以调用回调方法并在 python 中进行计算。
- 但现在我想将计算后的数据发送回用户,以便在向导中显示问题。所以我需要 运行 一些 JavaScript 函数。
我正在考虑创建一个虚拟按钮和 运行 这个按钮的点击方法来自 python。但我认为这是不可能的。
那么,我怎样才能 运行 一个 JavaScript 函数直接来自 python?
截至 Bokeh 0.12.6
,能够制作出这种 "Remote Procedure Calls" 仍然是 open feature request。
与此同时,最好的办法是在某些型号的 属性 上添加 CustomJS
callback。 CustomJS
可以执行任何你想要的 JS 代码(包括调用其他 JS 函数)并且会触发任何 属性 更新。
这是一个示例,显示每当更改滑块时调用 CustomJS
。对于您的用例,您可以添加一个不可见的圆形字形,并将 CustomJS
附加到字形的 size
属性。更改 glyph.size
是 "call" 函数的方式。
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import Figure, output_file, show
output_file("js_on_change.html")
x = [x*0.005 for x in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var f = cb_obj.value
x = data['x']
y = data['y']
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], f)
}
source.change.emit();
""")
slider = Slider(start=0.1, end=4, value=1, step=.1, title="power")
slider.js_on_change('value', callback)
layout = column(slider, plot)
show(layout)
显示 Bryan 回答我的内容的最小示例
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource
from bokeh.models.callbacks import CustomJS
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models.widgets import Button
plot = figure(
width=600,
height=600,
)
source = ColumnDataSource({
'x': [1, 2, 3],
'y': [4, 5, 6],
})
cr = plot.circle(
x='x', y='y',
source=source, size=10, color="navy", alpha=0.5
)
callback = CustomJS(args=dict(source=source), code="""
console.log('This code will be overwritten')
""")
cr.glyph.js_on_change('size', callback)
def cb():
js_code = """
alert('Hello!');
"""
callback.code = js_code # update js code
cr.glyph.size += 1 # trigger the javascript code
bt = Button(
label="Start Bokeh",
button_type="success"
)
bt.on_click(cb)
curdoc().add_root(column([bt, plot]))
我有这种情况:
- 我有一些数据(在 pandas 数据框中)用于绘制图表
- 当我按下按钮(由散景小部件构建)时,我可以调用回调方法并在 python 中进行计算。
- 但现在我想将计算后的数据发送回用户,以便在向导中显示问题。所以我需要 运行 一些 JavaScript 函数。
我正在考虑创建一个虚拟按钮和 运行 这个按钮的点击方法来自 python。但我认为这是不可能的。
那么,我怎样才能 运行 一个 JavaScript 函数直接来自 python?
截至 Bokeh 0.12.6
,能够制作出这种 "Remote Procedure Calls" 仍然是 open feature request。
与此同时,最好的办法是在某些型号的 属性 上添加 CustomJS
callback。 CustomJS
可以执行任何你想要的 JS 代码(包括调用其他 JS 函数)并且会触发任何 属性 更新。
这是一个示例,显示每当更改滑块时调用 CustomJS
。对于您的用例,您可以添加一个不可见的圆形字形,并将 CustomJS
附加到字形的 size
属性。更改 glyph.size
是 "call" 函数的方式。
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import Figure, output_file, show
output_file("js_on_change.html")
x = [x*0.005 for x in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var f = cb_obj.value
x = data['x']
y = data['y']
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], f)
}
source.change.emit();
""")
slider = Slider(start=0.1, end=4, value=1, step=.1, title="power")
slider.js_on_change('value', callback)
layout = column(slider, plot)
show(layout)
显示 Bryan 回答我的内容的最小示例
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource
from bokeh.models.callbacks import CustomJS
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models.widgets import Button
plot = figure(
width=600,
height=600,
)
source = ColumnDataSource({
'x': [1, 2, 3],
'y': [4, 5, 6],
})
cr = plot.circle(
x='x', y='y',
source=source, size=10, color="navy", alpha=0.5
)
callback = CustomJS(args=dict(source=source), code="""
console.log('This code will be overwritten')
""")
cr.glyph.js_on_change('size', callback)
def cb():
js_code = """
alert('Hello!');
"""
callback.code = js_code # update js code
cr.glyph.size += 1 # trigger the javascript code
bt = Button(
label="Start Bokeh",
button_type="success"
)
bt.on_click(cb)
curdoc().add_root(column([bt, plot]))