使用悬停工具获取最顶部图像的名称并在固定位置显示工具提示

Get the name of the top most image with hover tool and show the tooltip at a fixed position

我需要为同一图中的每个图指定一个名称。我想在图中悬停或点击时获得最顶部情节的名称。现在我使用 TextInput 来显示名称。在 CustomJS 内部,访问绘图名称的正确方法是什么?我四处搜索,但找不到有关 cb_objcb_data 内容的文档。感谢您的帮助。

示例代码:

from bokeh.server.server import Server
from bokeh.plotting import figure, ColumnDataSource, show
from bokeh.layouts import column
from bokeh.models import Button, HoverTool, TapTool, TextInput, CustomJS

import numpy as np

def make_document(doc):

    p = figure(match_aspect=True)
    img1 = np.random.rand(9, 9)
    img2= np.random.rand(9, 9)
    p.image(image=[img1], x=0, y=0, 
            dw=img1.shape[0], dh=img1.shape[1], 
            palette="Greys256", name='image1')
    p.image(image=[img2], x=5.5, y=5.5, 
            dw=img2.shape[0], dh=img2.shape[1], 
            palette="Greys256", name='image2')

    text_hover = TextInput(title='', value='', disabled=True)
    callback_hover = CustomJS(args=dict(text_hover=text_hover), code="""
        text_hover.value = cb_obj['geometry']['name']; 
        """) # what should be used here?

    hover_tool = HoverTool(callback=callback_hover, tooltips=None)
    p.add_tools(hover_tool)

    doc.add_root(column([p, text_hover], sizing_mode='stretch_both'))

apps = {'/': make_document}
server = Server(apps)
server.start()
server.io_loop.add_callback(server.show, "/")
try:
    server.io_loop.start()
except KeyboardInterrupt:
    print('keyboard interruption')
print('Done')

我注意到有一个 tags 参数,它可以在 CustomJS 中访问,但是如何访问?

tags (List ( Any )) –

An optional list of arbitrary, user-supplied values to attach to this model.

This data can be useful when querying the document to retrieve specific Bokeh models

Or simply a convenient way to attach any necessary metadata to a model that can be accessed by CustomJS callbacks, etc.

您只需要访问 p.title.text:

from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import TextInput, CustomJS, HoverTool
from bokeh.plotting import figure

p = figure(title="Hello there")
p.circle(0, 0)

text_hover = TextInput(title='', value='', disabled=True)
callback_hover = CustomJS(args=dict(text_hover=text_hover, plot=p),
                          code="text_hover.value = plot.title.text;")

p.add_tools(HoverTool(callback=callback_hover, tooltips=None))

show(column([p, text_hover]))

多方咨询,临时解决:

from bokeh.plotting import figure, ColumnDataSource, show
from bokeh.models import HoverTool, CustomJS
import numpy as np

img1 = np.random.rand(9, 9)
img2= np.random.rand(9, 9)

source = ColumnDataSource(dict(image=[img1, img2],
            name=['image1', 'image2'],
            x=[0, 5.5],
            y=[0, 5.5],
            dw=[img1.shape[0],  img2.shape[0]],
            dh=[img1.shape[1],  img2.shape[0]]))

p = figure(match_aspect=True)
render =p.image(source=source, image='image', x='x', y='y', dw='dw', dh='dh', name='name', palette="Greys256")

callback = CustomJS(code="""
                    var tooltips = document.getElementsByClassName("bk-tooltip");
                    for (var i = 0, len = tooltips.length; i < len; i ++) {
                    tooltips[i].style.top = ""; // unset what bokeh.js sets
                    tooltips[i].style.left = "";
                    tooltips[i].style.top = "0vh";
                    tooltips[i].style.left = "4vh";
                    }
                    """)

hover = HoverTool(renderers=[render], callback=callback)
hover.tooltips = """
    <style>
        .bk-tooltip>div:not(:last-child) {display:none;}
    </style>
    @name
"""
p.add_tools(hover)
show(p)