如何使用散景图的单击边缘的相应数据打开URL

时间:2019-02-19 14:35:12

标签: python bokeh

我正在尝试使用与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)

例如,将鼠标悬停在一条边缘上,该图像会显示在工具提示中:

http://localhost/blue/6

现在,我的目标是在单击边缘时在新选项卡中打开此URL。我正在使用带有OpenURL回调的TapTool。这次,使用来自最近的节点而不是边缘的信息来填充url模板。例如,它尝试打开:

http://localhost/color%20of%20node/???/X

是否可以按照我预期的方式使用OpenURL?

我猜我可以选择在TapTool中创建自定义JS回调,而不是使用OpenURL。我能够获得单击的字形的x和y位置,但是我不知道如何从单击的边缘检索数据信息以使用“颜色”和“重量”数据构建URL。任何想法如何实现这一目标?

1 个答案:

答案 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)