Bokeh - 如何让 HoverTool 工具提示在点击时保持在点上?
Bokeh - how to make HoverTool tooltips stick to points on click?
以下代码来自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 has an example of the type of behavior I would like to see. I know that this must be possible by either injecting some type of CustomJS or altering BokehJS coffescript 并从头开始构建 BokehJS,但我一直无法弄清楚。有没有人知道如何做到这一点?
更新:
可能会创建一个 custom tool using the tap_tool.coffee, hover_tool.coffee or tooltip.coffee。如果我弄明白了,我会更新这个。
这是在 models.HoverTool
的 'callback' 函数中使用 models.Label
创建您自己的悬停文本的解决方法。 models.TapTool
也用于切换更新标签文本。您无法编辑字形 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)
以下代码来自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 has an example of the type of behavior I would like to see. I know that this must be possible by either injecting some type of CustomJS or altering BokehJS coffescript 并从头开始构建 BokehJS,但我一直无法弄清楚。有没有人知道如何做到这一点?
更新:
可能会创建一个 custom tool using the tap_tool.coffee, hover_tool.coffee or tooltip.coffee。如果我弄明白了,我会更新这个。
这是在 models.HoverTool
的 'callback' 函数中使用 models.Label
创建您自己的悬停文本的解决方法。 models.TapTool
也用于切换更新标签文本。您无法编辑字形 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)