Fixed HoverTool TOOLTIPS when taping an element of a Bokeh plot

后端 未结 1 1633
小鲜肉
小鲜肉 2021-01-01 05:33

Similar to the hovertool, I would like that when I tap on an element of the plot (in this case a circle), there is a window that pop up with information reg

相关标签:
1条回答
  • 2021-01-01 06:35

    You can use TapTool callback like in the code below. Clicking a circle displays the tooltip. Clicking elsewhere on the plot or clicking the ResetTool hides the tooltip. The TapTool callback uses the same HoverTool tooltip as in your example and you can further customise it as you wish.

    See also this post which uses mini-plot as a tooltip.

    This code is for Bokeh v1.0.4

    from bokeh.plotting import figure, output_file, show, ColumnDataSource
    from bokeh.models import TapTool, CustomJS, HoverTool, Div, Row
    
    output_file("toolbar.html")
    
    source = ColumnDataSource(data = dict(
    x = [1, 2, 3, 3, 4],
    y = [2, 5, 8, 3, 6],
    desc = ['A', 'B', 'C', 'D', 'E'],
    imgs = ['https://docs.bokeh.org/static/snake.jpg',
            'https://docs.bokeh.org/static/snake2.png',
            'https://dods.bokeh.org/static/snake3D.png',
            'https://docs.bokeh.org/static/snake4_TheRevenge.png',
            'https://docs.bokeh.org/static/snakebite.jpg'],
    fonts = ['<i>italics</i>',
             '<pre>pre</pre>',
             '<b>bold</b>',
             '<small>small</small>',
             '<del>del</del>' ]))
    TOOLTIPS = """
    <div>
        <div>
            <img
                src="@imgs" height="42" alt="@imgs" width="42"
                style="float: left; margin: 0px 15px 15px 0px;"
                border="2"/>
        </div>
        <div width=60px>
            <span style="font-size: 17px; font-weight: bold;">@desc</span>
            <span style="font-size: 15px; color: #966;">[$index]</span>
        </div>
        <div>
            <span>@fonts{safe}</span>
        </div>
        <div>
            <span style="font-size: 15px;">Location</span>
            <span style="font-size: 10px; color: #696;">($x, $y)</span>
        </div>
    </div> """
    
    p = figure(plot_width = 400, plot_height = 400, x_range = (0, 6), y_range = (1, 9),
          title = "Mouse over the dots", tools = 'pan,wheel_zoom,save,reset,tap')
    circles = p.circle('x', 'y', size = 20, source = source)
    div = Div(text = '<div id="tooltip" style="position: absolute; display: none"></div>', name = 'tooltip')
    
    code = '''  if (cb_data.source.selected.indices.length > 0){
                    var selected_index = cb_data.source.selected.indices[0];
                    var tooltip = document.getElementById("tooltip");
    
                    tooltip.style.display = 'block';
                    tooltip.style.left = Number(cb_data.geometries.sx) + Number(20) + 'px';
                    tooltip.style.top = Number(cb_data.geometries.sy) - Number(20) + 'px';
    
                    tp = tp.replace('@imgs', cb_data.source.data.imgs[selected_index]);
                    tp = tp.replace('@desc', cb_data.source.data.desc[selected_index]);
                    tp = tp.replace('@fonts{safe}', cb_data.source.data.fonts[selected_index]);
                    tp = tp.replace('$index', selected_index);
                    tp = tp.replace('$x', Math.round(cb_data.geometries.x));
                    tp = tp.replace('$y', Math.round(cb_data.geometries.y));
                    tooltip.innerHTML = tp;
              } '''
    p.select(TapTool).callback = CustomJS(args = {'circles': circles, 'plot': p, 'tp': TOOLTIPS}, code = code)
    source.selected.js_on_change('indices', CustomJS(code = 'if (cb_obj.indices.length == 0) document.getElementById("tooltip").style.display = \"none\"'))
    layout = Row(p, div)
    show(layout)
    

    Result:

    0 讨论(0)
提交回复
热议问题