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

如何在Bokeh中选中节点时高亮其邻居节点及关联边?

解决方案

要实现点击节点时高亮自身、邻居节点及所有关联边的功能,Bokeh默认的选择策略无法满足需求,需要通过自定义JavaScript回调来手动控制选中状态。以下是完整的修改代码及关键步骤说明:

from bokeh.models import Circle, MultiLine, TapTool, CustomJS
from bokeh.io import show
from bokeh.models import Range1d, Plot
from bokeh.plotting import from_networkx
import networkx as nx

# 构建随机图
G = nx.gnm_random_graph(15, 30)

# 创建绘图容器
plot = Plot(x_range=Range1d(-2, 2), y_range=Range1d(-2, 2))

# 将NetworkX图转换为Bokeh可渲染对象
graph = from_networkx(G, nx.spring_layout, scale=1.8, center=(0,0))
plot.renderers.append(graph)

# 设置节点和边的默认样式
graph.node_renderer.glyph = Circle(size=25, fill_color='#2b83ba')
graph.edge_renderer.glyph = MultiLine(line_color="#cccccc", line_alpha=0.8, line_width=2)

# 设置选中状态下的样式
graph.node_renderer.selection_glyph = Circle(size=25, fill_color='#abdda4')
graph.edge_renderer.selection_glyph = MultiLine(line_color='#abdda4', line_width=4)

# 关闭默认选择策略,改用自定义逻辑
graph.selection_policy = None

# 获取节点和边的数据源对象
node_source = graph.node_renderer.data_source
edge_source = graph.edge_renderer.data_source

# 提前将每个节点的邻居列表存入节点数据源,供JS回调使用
node_source.data['neighbors'] = [list(G.neighbors(n)) for n in G.nodes()]

# 定义自定义JS回调,处理点击事件后的选中逻辑
callback = CustomJS(args=dict(node_source=node_source, edge_source=edge_source), code="""
    // 获取点击选中的节点索引
    const selected_node = node_source.selected.indices[0];
    if (typeof selected_node === 'undefined') return;
    
    // 获取该节点的邻居列表
    const neighbors = node_source.data.neighbors[selected_node];
    
    // 组合原节点与所有邻居,形成需高亮的节点集合
    const target_nodes = [selected_node, ...neighbors];
    
    // 筛选出所有连接目标节点的边
    const selected_edges = [];
    const starts = edge_source.data.start;
    const ends = edge_source.data.end;
    
    for (let i = 0; i < starts.length; i++) {
        // 仅保留两端都在目标节点集合中的边
        if (target_nodes.includes(starts[i]) && target_nodes.includes(ends[i])) {
            selected_edges.push(i);
        }
    }
    
    // 更新节点和边的选中状态
    node_source.selected.indices = target_nodes;
    edge_source.selected.indices = selected_edges;
    
    // 通知数据源更新,触发视图刷新
    node_source.change.emit();
    edge_source.change.emit();
""")

# 给TapTool绑定自定义回调
tap_tool = TapTool()
tap_tool.callback = callback
plot.add_tools(tap_tool)

show(plot)

关键逻辑说明

  1. 关闭默认选择策略:设置graph.selection_policy = None,避免Bokeh默认的选中逻辑覆盖自定义操作。
  2. 预存邻居信息:将每个节点的邻居列表提前存入节点数据源的neighbors字段,让JavaScript可以直接读取,无需在前端处理图结构。
  3. 自定义选中逻辑:
    • 获取点击的节点索引,取出对应的邻居列表。
    • 组合原节点与邻居形成目标节点集合,筛选出所有连接这些节点的边。
    • 更新节点和边的选中索引,触发数据源刷新以应用高亮样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:40:33