简体   繁体   English

如何使用Bokeh从Python调用JavaScript函数?

[英]How can I call a JavaScript function from Python using Bokeh?

I have this scenario: 我有这种情况:

  1. I have some data (in a pandas dataframe) that I use to draw my plots 我有一些数据(在pandas数据框中)用于绘制图
  2. When I press a button (built by a bokeh widget) I can call my callback method and I do my computation in python. 当我按下一个按钮(由bokeh小部件构建)时,我可以调用回调方法,并使用python进行计算。
  3. But now I want to send the computed data back to the user in order to show a question in a wizard. 但是现在我想将计算的数据发送回用户,以便在向导中显示问题。 So I need to run some JavaScript function. 所以我需要运行一些JavaScript函数。

I was thinking of creating a dummy button and run the click method of this button from python. 我正在考虑创建一个虚拟按钮并从python运行此按钮的click方法。 But I think this is not possible. 但是我认为这是不可能的。

So, how can I run a JavaScript function directly from python? 那么,如何直接从python运行JavaScript函数?

As of Bokeh 0.12.6 , being able to make these kinds of "Remote Procedure Calls" is still an open feature request . 从Bokeh 0.12.6 ,能够进行此类“远程过程调用”仍然是一项开放功能要求

In the mean time, your best bet is to add a CustomJS callback to some property of some model. 同时,最好的选择是将CustomJS回调添加到某些模型的某些属性。 The CustomJS can execute whatever JS code you want (including calling other JS functions) and will trigger any the property is updated. CustomJS可以执行您想要的任何JS代码(包括调用其他JS函数),并将触发任何属性更新。

Here's an example that shows calling CustomJS whenever a slider is changed. 这是一个示例,该示例显示在更改滑块时调用CustomJS For your use case you might add an invisible circle glyph, and attach a CustomJS to the glyph's size attribute. 对于您的用例,您可以添加一个不可见的圆形字形,并将CustomJS附加到该字形的size属性。 Changing glyph.size is how you can "call" the function. 更改glyph.size是您可以“调用”函数的方式。

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)

Minimal example showing what Bryan answered me 最小的例子显示布莱恩回答了我

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]))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM