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

如何在Bokeh绘图中为圆形添加点击回调并关联ColumnDataSource记录?

当然可以给Bokeh里的圆形添加点击回调!我给你分两种常用场景讲具体实现方式,你可以根据自己的需求选择:

方法一:使用JavaScript回调(无需Bokeh Server)

如果你的可视化是静态HTML输出,不需要后端服务,这种方式最适合。核心思路是用TapTool捕捉点击事件,再通过CustomJS编写前端回调逻辑来获取对应记录。

完整代码示例:

from bokeh.models import ColumnDataSource, TapTool, CustomJS
from bokeh.plotting import figure, show

# 定义你的数据源(替换成你实际的数据)
source = ColumnDataSource(data={
    'longitude': [1, 2, 3, 4],
    'latitude': [5, 6, 7, 8],
    'id': ['rec1', 'rec2', 'rec3', 'rec4']  # 示例关联的记录标识
})

bound = 10
fig = figure(x_range=(-bound, bound), y_range=(-bound, bound), plot_width=800, plot_height=500, output_backend="webgl")
# 绘制圆形,保存这个renderer对象用于关联TapTool
circles = fig.circle(x='longitude', y='latitude', size=2, source=source)

# 创建TapTool并绑定JS回调
tap_tool = TapTool(renderers=[circles])
callback = CustomJS(args=dict(source=source), code="""
    // 获取点击的圆形对应的数据源索引
    const selectedIndices = source.selected.indices;
    if (selectedIndices.length > 0) {
        const idx = selectedIndices[0];
        // 从数据源中取出对应记录的所有字段
        const clickedRecord = {
            longitude: source.data.longitude[idx],
            latitude: source.data.latitude[idx],
            id: source.data.id[idx]
        };
        
        // 这里写你需要的操作,比如打印到控制台、更新页面元素等
        console.log('点击的记录:', clickedRecord);
        alert(`选中记录ID: ${clickedRecord.id},坐标: (${clickedRecord.longitude}, ${clickedRecord.latitude})`);
    }
""")
tap_tool.callback = callback
fig.add_tools(tap_tool)

show(fig)

关键说明:

  • TapTool(renderers=[circles])确保只响应这个圆形图层的点击,不会触发其他元素的事件。
  • 通过source.selected.indices拿到点击位置对应的数据源索引,再从source.data的数组中取出对应位置的字段值,就能获取完整记录。
方法二:使用Python回调(需要Bokeh Server)

如果你的应用需要后端处理逻辑(比如操作数据库、调用API),可以用Bokeh Server实现Python回调,直接在后端获取并处理点击的记录。

完整代码示例:

from bokeh.models import ColumnDataSource, TapTool
from bokeh.plotting import figure, curdoc
from bokeh.events import Tap

# 定义数据源
source = ColumnDataSource(data={
    'longitude': [1, 2, 3, 4],
    'latitude': [5, 6, 7, 8],
    'id': ['rec1', 'rec2', 'rec3', 'rec4']
})

bound = 10
fig = figure(x_range=(-bound, bound), y_range=(-bound, bound), plot_width=800, plot_height=500, output_backend="webgl")
circles = fig.circle(x='longitude', y='latitude', size=2, source=source)

# 定义Python回调函数
def handle_circle_tap(event):
    # 获取选中的索引
    selected_indices = source.selected.indices
    if selected_indices:
        idx = selected_indices[0]
        # 提取对应记录
        clicked_record = {
            'id': source.data['id'][idx],
            'longitude': source.data['longitude'][idx],
            'latitude': source.data['latitude'][idx]
        }
        print('后端收到点击记录:', clicked_record)
        # 这里可以添加后端逻辑,比如写入数据库、调用第三方接口等

# 绑定回调到Tap事件
fig.on_event(Tap, handle_circle_tap)

# 添加TapTool确保选择功能生效
tap_tool = TapTool(renderers=[circles])
fig.add_tools(tap_tool)

curdoc().add_root(fig)

运行方式:

保存代码为circle_tap_app.py,然后在终端执行:

bokeh serve --show circle_tap_app.py

点击圆形时,后端控制台会打印出对应的记录,你可以在handle_circle_tap函数里添加任何Python逻辑。

注意事项:

  • 如果需要支持多选,可以调整TapTool的behavior参数,或者使用BoxSelectTool等工具,但单点击场景用TapTool就足够了。
  • 两种方式中,确保renderers参数正确关联了你绘制的圆形对象,避免误触发其他图层的点击事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:39:47