Skip to content

Hover information solely on the x and y axes, like tradingview #7518

@NeoWang9999

Description

@NeoWang9999

Image
Similar to the TradingView chart above, how can I ensure that the x-axis and y-axis always display the current mouse hover position values when using spikemode=‘across’ and spikesnap=‘cursor’ in Plotly?
This is particularly useful for financial chart analysis, similar to the effect I achieved using Dash’s callback function. However, it would be preferable if Plotly could support this natively. Below is a simple code snippet demonstrating how to achieve this functionality using Dash (for illustrative purposes only).

import dash
from dash import dcc, html, Input, Output, State
import plotly.graph_objects as go
import numpy as np

app = dash.Dash(__name__)

# 生成示例数据
x = np.linspace(0, 10, 100)
y = np.sin(x)

fig = go.Figure(go.Scatter(x=x, y=y))
fig.update_layout(
    yaxis=dict(
        side="right",  # Y 轴在右侧
        spikemode="across",  # 横线横穿到 Y 轴
        spikesnap="cursor",  # 吸附到鼠标
        spikethickness=1,
        spikecolor="#999",
        showticklabels=True,  # 隐藏默认刻度标签
        # ticks=""  # 隐藏刻度线
    ),
    hoverdistance=100,
    spikedistance=1000,
    showlegend=True,
    hovermode='xy',
)

app.layout = html.Div([
    dcc.Graph(id="graph", figure=fig),
    dcc.Store(id="mouse-data")  # 存储鼠标位置
])


@app.callback(
    Output("graph", "figure"),
    Input("graph", "hoverData"),
    State("graph", "figure")
)
def update_annotation(hover_data, fig):
    if not hover_data:
        # 无悬停时,移除注释
        fig["layout"].pop("annotations", None)
        return fig

    # 获取悬停点的 Y 值
    y_val = hover_data["points"][0]["y"]

    # 添加动态注释(右侧 Y 轴对应位置)
    fig["layout"]["annotations"] = [{
        "x": 1,  # 绘图区右侧边缘(x 轴比例 0~1)
        "y": y_val,
        "xref": "paper",  # x 基于绘图区比例
        "yref": "y",  # y 基于 Y 轴数值
        "text": f"{y_val:.2f}",  # 显示 Y 值(保留2位小数)
        "showarrow": False,
        "xanchor": "left",  # 文本左对齐(紧贴 Y 轴)
        "bgcolor": "white",  # 白色背景
        "bordercolor": "#ccc",  # 边框颜色
        "borderwidth": 1,  # 边框宽度
        "borderpad": 6,  # 边框内边距
    }]
    return fig


if __name__ == "__main__":
    app.run(debug=True, port=8051)

related issue:
#2026
#5036

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions