You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bokeh图表的轴端显示鼠标移动时的坐标信息?

在Bokeh中实现鼠标移动时轴端实时显示时间与价格

可以通过CustomJS回调+自定义文本元素实现需求,无需依赖HoverTool或Crosshair工具的限制。以下是两种实现方案:

方案1:在图表旁实时显示信息

这种方式将信息放在图表右侧,布局清晰直观:

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, Div, Row
from bokeh.sampledata.stocks import AAPL
import pandas as pd

# 处理示例数据
df = pd.DataFrame(AAPL)
df['date'] = pd.to_datetime(df['date'])
source = ColumnDataSource(data=df)

# 创建基础图表
p = figure(x_axis_type='datetime', y_axis_label='Price', width=800, height=400, tools='pan,wheel_zoom,reset')
p.line('date', 'close', source=source)

# 创建用于展示实时信息的Div容器
info_panel = Div(
    text='<div style="font-size:14px; padding:10px;">日期:<span id="date"></span><br>价格:<span id="price"></span></div>',
    width=200
)

# 自定义鼠标移动事件回调
mouse_move_callback = CustomJS(args=dict(p=p, info_panel=info_panel), code="""
    // 获取鼠标屏幕坐标
    const screen_x = cb_obj.x;
    const screen_y = cb_obj.y;

    // 将屏幕坐标转换为数据空间的实际值
    const data_x = p.x_scale.invert(screen_x);
    const data_y = p.y_scale.invert(screen_y);

    // 格式化日期和价格
    const date_str = new Date(data_x).toLocaleDateString();
    const price_str = '$' + data_y.toFixed(2);

    // 更新面板显示内容
    info_panel.text = `<div style="font-size:14px; padding:10px;">日期:<span id="date">${date_str}</span><br>价格:<span id="price">${price_str}</span></div>`;
""")

# 绑定鼠标移动事件
p.js_on_event('mousemove', mouse_move_callback)

# 组合图表和信息面板
layout = Row(p, info_panel)
show(layout)

方案2:直接在轴端显示信息

如果希望信息紧贴轴的末端(如x轴右侧、y轴顶部),可以使用Text元素并动态更新位置:

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, Text
from bokeh.sampledata.stocks import AAPL
import pandas as pd

# 处理数据
df = pd.DataFrame(AAPL)
df['date'] = pd.to_datetime(df['date'])
source = ColumnDataSource(data=df)

# 创建图表
p = figure(x_axis_type='datetime', y_axis_label='Price', width=800, height=400, tools='pan,wheel_zoom,reset')
p.line('date', 'close', source=source)

# 创建轴端文本元素
date_label = Text(x=[0], y=[p.plot_height + 20], text=[''], text_align='right', text_font_size='12pt')
price_label = Text(x=[-20], y=[0], text=[''], text_align='right', text_font_size='12pt', angle=90)

# 将文本元素添加到图表布局
p.add_layout(date_label, 'above')
p.add_layout(price_label, 'left')

# 自定义回调逻辑
axis_label_callback = CustomJS(args=dict(p=p, date_label=date_label, price_label=price_label), code="""
    const screen_x = cb_obj.x;
    const screen_y = cb_obj.y;

    const data_x = p.x_scale.invert(screen_x);
    const data_y = p.y_scale.invert(screen_y);

    // 格式化显示内容
    const date_str = new Date(data_x).toLocaleDateString();
    const price_str = '$' + data_y.toFixed(2);

    // 更新文本内容和位置(始终固定在轴端)
    date_label.text = [date_str];
    date_label.x = [p.plot_width];
    
    price_label.text = [price_str];
    price_label.y = [p.plot_height];
""")

p.js_on_event('mousemove', axis_label_callback)
show(p)

关键说明

  • 使用js_on_event('mousemove')监听鼠标移动事件,实时获取屏幕坐标
  • 通过x_scale.invert()和y_scale.invert()将屏幕坐标转换为数据空间的实际值(日期、价格)
  • 可以根据需求调整格式化规则(如日期显示精度、价格小数位数)

内容的提问来源于stack exchange,提问作者forraxa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:56:08