散景 - 如何使HoverTool工具提示坚持点击点?

时间:2017-01-13 17:48:16

标签: javascript python jupyter-notebook jupyter bokeh

以下代码来自jupyter notebook

from bokeh.io import show, output_notebook
from bokeh.plotting import ColumnDataSource, figure
from bokeh.models import HoverTool, Range1d

output_notebook()
fig = figure(tools=[HoverTool(tooltips=[("html", '@html{safe}')])])

fig.quad(left="left", top="top", bottom="bottom", right="right",
         source=ColumnDataSource({"left": [1,3], "bottom": [1,3],
                                  "right": [2,4], "top": [2,4],
                                  "html":["<b>I'm bold</b>", "<span 

style='color:red;font-size:32px;'>BIG RED TEXT</span>"]}))
    show(fig)

我需要让HoverTool工具提示贴在他们单击该点的确切位置,因此如果用户想突出显示并在工具提示中复制文本,他们可以。这个codepen有一个我希望看到的行为类型的例子。我知道这必须通过注入某种类型的CustomJS或改变BokehJS coffescript并从头开始构建BokehJS来实现,但我还没有能够弄明白。有没有人知道如何做到这一点?

更新:
可以使用custom tooltap_tool.coffeehover_tool.coffee创建tooltip.coffee。如果我搞清楚,我会更新这个。

1 个答案:

答案 0 :(得分:1)

这是一种解决方法,在models.Label的“回调”功能中使用models.HoverTool创建自己的悬停文本。此外,models.TapTool用于切换更新Label文本。您无法编辑字形models.Label中的文字,但已添加TextInput widget,其中文字更新为将图形字形悬停在其中。

import bokeh
import bokeh.plotting
fig = bokeh.plotting.figure()

d_source = bokeh.models.ColumnDataSource({"left": [1,3,1],
                "bottom": [1,3,3],"right": [2,4,2],"top": [2,4,4]})
h_source = bokeh.models.ColumnDataSource({"do_hover":[True,True]  })
fig.quad(left="left", top="top", bottom="bottom", right="right",
         source=d_source)

myToolTip = bokeh.models.Label(x=2.5,y=2.5, text="",
                               background_fill_color = "#ffffff")

HoverCallback = bokeh.models.CustomJS(args=dict(d_source=d_source,
                    myToolTip=myToolTip,h_source=h_source),code="""
        function findWhereIam(x,y,s){
            // To find where the cursor is. 
            selection = -1;
            for (i = 0; i < s.data.left.length; i++) {
                x0 = s.data.left[i];
                x1 = s.data.right[i];
                y0 = s.data.bottom[i];
                y1 = s.data.top[i];
                if (x>x0 && x<x1 && y>y0 && y<y1){
                    // It's inside rectangle!!!
                    selection = i;
                }
            }
            return selection
        }
        if (h_source.data.do_hover[0]){
            x_data = cb_data['geometry'].x;
            y_data = cb_data['geometry'].y;
            var selection = findWhereIam(x_data,y_data,d_source)
            if (selection>=0){
                x0 = d_source.data.left[selection];
                x1 = d_source.data.right[selection];
                y0 = d_source.data.bottom[selection];
                y1 = d_source.data.top[selection];
                myToolTip.x = 0.5 * (x0+x1);
                myToolTip.y = 0.5 * (y0+y1);
                myToolTip.text = "on:"+selection;
                myToolTip.text_font_size = "24pt";
                myToolTip.background_fill_color = "#ffffff";
                myToolTip.border_line_color = "#000000";
                myToolTip.text_align = "center";
                myToolTip.trigger('change');

                current_selection.value = myToolTip.text;
                current_selection.trigger('change');
            }else{
                myToolTip.text = ""; //erase
                myToolTip.trigger('change');
                current_selection.value = myToolTip.text;
                current_selection.trigger('change');
            }
        }
    """)

TapCallback = bokeh.models.CustomJS(args=dict(h_source=h_source), code="""
        h_source.data.do_hover[0] = !h_source.data.do_hover[0];
    """)

current_selection = bokeh.models.widgets.TextInput(value="",
                                                   title="Selection")

HoverCallback.args.update(dict(current_selection=current_selection))

fig.add_tools(bokeh.models.HoverTool(tooltips=None,callback=HoverCallback))
fig.add_tools(bokeh.models.TapTool(callback=TapCallback))
fig.add_layout(myToolTip)
page = bokeh.plotting.gridplot([[fig],[current_selection]])
bokeh.io.output_notebook()
bokeh.io.show(page)

enter image description here