如何在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)
关键逻辑说明
- 关闭默认选择策略:设置
graph.selection_policy = None,避免Bokeh默认的选中逻辑覆盖自定义操作。 - 预存邻居信息:将每个节点的邻居列表提前存入节点数据源的
neighbors字段,让JavaScript可以直接读取,无需在前端处理图结构。 - 自定义选中逻辑:
- 获取点击的节点索引,取出对应的邻居列表。
- 组合原节点与邻居形成目标节点集合,筛选出所有连接这些节点的边。
- 更新节点和边的选中索引,触发数据源刷新以应用高亮样式。
内容的提问来源于stack exchange,提问作者robinood
相关产品推荐
相关产品推荐

