My goal is to add an HoverTool
to my figure which displays the weekday by name. The date is defined by the x-axis values. I want to display this information at a fixed position even if the visible section is changed by a tool like BoxZoom
.
Since the HoverTool needs at least one renderer I first tried to define a line but I did not find a way to define the position relative to the figure. In fact if I zoom it can happen, that this line is not in the visible part and the HoverTool isn't working anymore (or in an area which is not visible).
My second attempt was to define an extra_y_range
to draw the line relative. But I did not find a way to unselect the BoxZoom for this axis.
import pandas as pd
from bokeh.plotting import figure, output_notebook, show
from bokeh.models import (
HoverTool,
LinearAxis,
Range1d,
)
output_notebook()
dr = pd.date_range('2020-01-01', '2020-01-05', freq='D')
p = figure(title="line", plot_width=300, plot_height=300, x_axis_type='datetime')
p.line(x=dr, y=[6, 7, 2, 4, 5])
p.extra_y_ranges.update({"extra": Range1d(0, 1)})
p.add_layout(LinearAxis(y_range_name="extra", axis_label=''), "right")
l = p.line(x=dr, y=0.8, color='gray', **{"y_range_name":"extra"})
p.add_tools(
HoverTool(
tooltips=[("", "@x{%A}")],
renderers=[l],
mode="vline",
formatters={"@x": "datetime"},
))
show(p)
Is there a way to add an HoverTool which stays at the same position in the visible area even if this area is effected by tools?
You can try this solution which works for Bokeh v2.1.1. In the code below the tooltip is fixed at absolute position on the screen. You can add yourself more generic solution independent of the plot position on the screen.
from bokeh.models import CustomJS
from bokeh.models import HoverTool
from bokeh.plotting import show, figure
import numpy as np
p = figure(plot_width = 300, plot_height = 300, tooltips = [('value X', '@x'), ('value Y', '@y')])
circles = p.circle(x=np.random.rand(10)*10, y=np.random.rand(10)*10, size=10)
callback = CustomJS(args={'p': p}, code="""
var tooltips = document.getElementsByClassName("bk-tooltip");
const tw = 100;
for (var i = 0; i < tooltips.length; i++) {
tooltips[i].style.top = '5px';
tooltips[i].style.left = p.width/2 - tw/2 + 'px';
tooltips[i].style.width = tw + 'px';
} """)
hover = p.select_one(HoverTool)
hover.renderers = [circles]
hover.callback = callback
hover.show_arrow = False
show(p)
For Bokeh v3, change the string
bk-tooltip
tobk-Tooltip
with a capital T.