我有一个名为 getcoords.py 的 Bokeh 服务器应用程序。我用以下命令启动服务器:bokeh serve getcoords.py
。我有一个带有 CustomJS
回调函数的 HoverTool
。此外,我还有一个 quad
glyph
和 on_change
配置为触发服务器端的 selected
事件。每次我点击 quad
glyph
时,都会执行 onTab
函数。当我点击字形时,我想以某种方式与客户端通信并获取指针坐标。这是代码:
import bokeh
import bokeh.plotting
p = bokeh.plotting.figure(plot_height=200,x_range=(0,10),y_range=(0,10))
imquad = p.quad(top=[8], bottom=[2], left=[2], right=[8])
sourceXY = bokeh.models.ColumnDataSource(data=dict(x = [0], y = [0]))
callback_hover = bokeh.models.CustomJS(args=dict(sourceXY=sourceXY), code="""
console.log('Coords:'+sourceXY.data['x'] +','+sourceXY.data['y'])
sourceXY.data['x'] = [cb_data['geometry'].x];
sourceXY.data['y'] = [cb_data['geometry'].y];
sourceXY.trigger('change');
""")
def onHover(attr, old, new):
print "Hover"
counter = 0
def onTab(attr, old, new):
global counter
print "Tap on quad. Coordinates:",sourceXY.data['x'], sourceXY.data['y']
sourceXY.data['x'], sourceXY.data['y'] = [counter],[counter]
counter += 1
sourceXY.trigger('data',None,None)
# unselecting imquad to keep triggering on_change:
new['1d']['indices'] = []
imquad.data_source.on_change('selected',onTab)
hover_tool = bokeh.models.HoverTool(callback=callback_hover)
tap_tool = bokeh.models.TapTool()
p.add_tools(tap_tool)
p.add_tools(hover_tool)
bokeh.io.curdoc().add_root(p)
这是显示 JavaScript
控制台日志的浏览器屏幕截图。 Coords:0,0 1,1 2,2 3,3 4,4 对应于单击四边形字形的时刻,这些值从服务器发送到客户端浏览器。 javascript CustomJS
代码首先显示 sourceXY 的值,然后用 x 和 y 数据坐标替换它。当您移动鼠标时,sourceXY 会使用这些坐标进行更新,只要您不点击,它们就会显示在 JS 控制台中。
这是服务器端控制台的屏幕截图。每次点击四边形字形时,都会执行 onTab(attr, old, new) 例程。首先它显示存储在 sourceXY 中的值,然后它分配一个全局计数器值,该值在每次执行例程时增加 1。这是我希望能够从客户端读取 sourceXY 的值,但我无法做到这一点。
wirelessprv-XX-XXX-XXX-XXX:GetCoords pablo$ bokeh serve getcoords.py
2017-02-25 21:26:00,899 Starting Bokeh server version 0.12.4
2017-02-25 21:26:00,911 Starting Bokeh server on port 5006 with applications at paths ['/getcoords']
2017-02-25 21:26:00,912 Starting Bokeh server with process id: 36965
2017-02-25 21:26:01,267 200 GET /getcoords (::1) 85.38ms
2017-02-25 21:26:01,785 WebSocket connection opened
2017-02-25 21:26:01,788 ServerConnection created
Tap on quad. Coordinates: [0] [0]
Tap on quad. Coordinates: [0] [0]
Tap on quad. Coordinates: [1] [1]
Tap on quad. Coordinates: [2] [2]
Tap on quad. Coordinates: [3] [3]
我尝试的是创建一个名为 sourceXY 的 ColumnDataSource
,它在 CustomJS
客户端中更新。然后当我点击字形时,服务器端的 python 代码读取服务器端 ColumnDataSource
的值,该值尚未更新,然后修改它以测试服务器到客户端的通信。该部分工作得很好,因为客户端能够读取从服务器发送的 x 和 y。
我想知道是否有办法从客户端到服务器端获取保存在 ColumnDataSource
中的坐标(或点击发生时的坐标本身)。
欢迎任何建议,评论。谢谢。
最佳答案
我找到了一种将坐标值从服务器更新到客户端的方法。我找到了从 HoverTool
的 CustomJS
javascript 回调更新 TextInput
模型的解决方案。我会把我的解决方案放在这里,以防有人能从中受益。
import bokeh
import bokeh.plotting
p = bokeh.plotting.figure(plot_height=200,x_range=(0,10),y_range=(0,10))
imquad = p.quad(top=[8], bottom=[2], left=[2], right=[8])
textxy = bokeh.models.TextInput(title="xy val", value='')
callback_hover = bokeh.models.CustomJS(args=dict(textxy=textxy), code="""
textxy.value = cb_data['geometry'].x + ',' + cb_data['geometry'].y;
console.log(textxy.value);
""")
def onTab(attr, old, new):
print "tap:",textxy.value
# unselecting imquad to keep triggering on_change:
new['1d']['indices'] = []
imquad.data_source.on_change('selected',onTab)
hover_tool = bokeh.models.HoverTool(callback=callback_hover)
tap_tool = bokeh.models.TapTool()
p.add_tools(tap_tool)
p.add_tools(hover_tool)
bokeh.io.curdoc().add_root(p)
每次我点击 quad
glyph
时,控制台的输出都会显示正确的坐标:
wirelessprv-XXX-XXX-XXX-XXX:GetCoords pablo$ bokeh serve getcoords.py
2017-02-26 18:09:44,189 Starting Bokeh server version 0.12.4
2017-02-26 18:09:44,199 Starting Bokeh server on port 5006 with applications at paths ['/getcoords']
2017-02-26 18:09:44,199 Starting Bokeh server with process id: 42626
2017-02-26 18:09:46,841 200 GET /getcoords (::1) 68.90ms
2017-02-26 18:09:47,282 WebSocket connection opened
2017-02-26 18:09:47,283 ServerConnection created
tap: 3.3528435714104643,3.925695345068399
tap: 5.715666419702689,6.670813794893257
tap: 6.649805685306592,3.341627589786514
tap: 7.913641162300107,2.407119181335499
tap: 7.913641162300107,7.66372897887246
更新新的 Bokeh 版本。测试于 0.12.16
要使这种方法起作用,需要将 TextInput 模型添加到客户端布局中。在这里它被添加为一行的一部分并且被禁用:
import bokeh
import bokeh.plotting
p = bokeh.plotting.figure(plot_height=200,x_range=(0,10),y_range=(0,10))
imquad = p.quad(top=[8], bottom=[2], left=[2], right=[8])
textxy = bokeh.models.TextInput(title="xy val", value='',disabled=True)
callback_hover = bokeh.models.CustomJS(args=dict(textxy=textxy), code="""
textxy.value = cb_data['geometry'].x + ',' + cb_data['geometry'].y;
console.log(textxy.value);
""")
def onTab(attr, old, new):
print "tap:",textxy.value
imquad.data_source.on_change('selected',onTab)
hover_tool = bokeh.models.HoverTool(callback=callback_hover)
tap_tool = bokeh.models.TapTool()
p.add_tools(tap_tool)
p.add_tools(hover_tool)
layout = bokeh.layouts.row(p,textxy)
bokeh.io.curdoc().add_root(layout)
应该提到的是,bokeh.models.Div
模型可以以相同的方式发送在 CustomJS
回调函数中更新的 x,y 坐标。
关于javascript - 在 Bokeh 服务器配置中如何从客户端浏览器获取 x,y 坐标到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42464500/