我正在尝试使用与Bokeh渲染的networkx图的 edge 相对应的参数打开一个URL。我能够使用带有工具提示的HoverTool来加载与所需URL匹配的图像,该URL是一个模板,模板中填充了图形的Edge数据中的参数(“颜色”和“权重”)。这是一个简化的示例:
import networkx as nx
from bokeh.io import show, output_file
from bokeh.models import Plot, Range1d, MultiLine, Circle, TapTool, OpenURL, HoverTool
from bokeh.models.graphs import from_networkx, EdgesAndLinkedNodes
from bokeh.palettes import Spectral4
tooltips = """
<div id="picture" style="width : 550px; position: fixed; left: 250px; top: 80px">
<div>
<img
src="http://localhost/@color/@weight/" alt="http://localhost/@color/@weight/" height=300
border="2"
></img>
</div>
</div>
"""
G = nx.Graph()
G.add_node('X', color='color of node')
G.add_edge('Y', 'X', weight=6, color="blue")
G.add_edge('Z', 'X', weight=3, color="yellow")
G.add_edge('Y', 'Z', weight=7, color="red")
plot = Plot(plot_width=800, plot_height=800,
x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
graph_renderer = from_networkx(G, nx.circular_layout, scale=1, center=(0,0))
graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])
graph_renderer.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2])
graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1])
graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5)
graph_renderer.edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=5)
graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)
graph_renderer.selection_policy = EdgesAndLinkedNodes()
graph_renderer.inspection_policy = EdgesAndLinkedNodes()
plot.renderers.append(graph_renderer)
url = "http://localhost/@color/@weight/@index"
plot.add_tools(HoverTool(tooltips=tooltips), TapTool(callback=OpenURL(url=url)))
output_file("example.html")
show(plot)
例如,将鼠标悬停在一条边缘上,该图像会显示在工具提示中:
现在,我的目标是在单击边缘时在新选项卡中打开此URL。我正在使用带有OpenURL回调的TapTool。这次,使用来自最近的节点而不是边缘的信息来填充url模板。例如,它尝试打开:
http://localhost/color%20of%20node/???/X
是否可以按照我预期的方式使用OpenURL?
我猜我可以选择在TapTool中创建自定义JS回调,而不是使用OpenURL。我能够获得单击的字形的x和y位置,但是我不知道如何从单击的边缘检索数据信息以使用“颜色”和“重量”数据构建URL。任何想法如何实现这一目标?
答案 0 :(得分:2)
您可以将URL传递到JS回调并使用open()
方法打开它,如下例所示。点击一个节点会将回调对象cb_obj
,回调数据cb_data
和其他信息打印到开发者工具控制台,例如在Google Chrome中。还将打印选定的索引和相应的数据值。请注意,在执行此JS回调之前,将首先应用graph_renderer.selection_policy
。希望对您有帮助
import networkx as nx
from bokeh.io import show, output_file
from bokeh.models import Plot, Range1d, MultiLine, Circle, TapTool, OpenURL, HoverTool, CustomJS
from bokeh.models.graphs import from_networkx, EdgesAndLinkedNodes
from bokeh.palettes import Spectral4
tooltips = """
<div id="picture" style="width : 550px; position: fixed; left: 250px; top: 80px">
<div>
<img
src="http://localhost/@color/@weight/" alt="http://localhost/@color/@weight/" height=300
border="2"
></img>
</div>
</div> """
G = nx.Graph()
G.add_node('X', color = 'color of node')
G.add_edge('Y', 'X', weight = 6, color = "blue")
G.add_edge('Z', 'X', weight = 3, color = "yellow")
G.add_edge('Y', 'Z', weight = 7, color = "red")
plot = Plot(x_range = Range1d(-1.1, 1.1), y_range = Range1d(-1.1, 1.1))
graph_renderer = from_networkx(G, nx.circular_layout, scale = 1, center = (0, 0))
graph_renderer.node_renderer.glyph = Circle(size = 15, fill_color = Spectral4[0])
graph_renderer.node_renderer.selection_glyph = Circle(size = 15, fill_color = Spectral4[2])
graph_renderer.node_renderer.hover_glyph = Circle(size = 15, fill_color = Spectral4[1])
graph_renderer.edge_renderer.glyph = MultiLine(line_color = "#CCCCCC", line_alpha = 0.8, line_width = 5)
graph_renderer.edge_renderer.selection_glyph = MultiLine(line_color = Spectral4[2], line_width = 5)
graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color = Spectral4[1], line_width = 5)
graph_renderer.selection_policy = EdgesAndLinkedNodes()
graph_renderer.inspection_policy = EdgesAndLinkedNodes()
plot.renderers.append(graph_renderer)
url = "http://localhost/@color/@weight/@index"
code = '''
//open(url);
console.log(cb_obj);
console.log(cb_data);
console.log(cb_data.source.selected.indices);
console.log(cb_data.source.data);
selected = cb_data.source.selected.indices
if (selected.length > 0)
for (index in selected)
console.log('index: ' + selected[index] + ', value: ' + cb_data.source.data.index[selected[index]])
console.log(''); '''
callback_tap_tool = CustomJS(args = dict(url = url), code = code)
plot.add_tools(HoverTool(tooltips = tooltips), TapTool(callback = callback_tap_tool))
output_file("example.html")
show(plot)