Hello,
I am plotting a Sankey chart on my Dash app along with the dcc.Tooltip
to display info on hover as the styling of the default graph tooltip doesn’t fit my requirements.
However the tooltip positioning is not aligned to the center of the sankey node
I’m passing the bbox coordinates from the hoverData
of the graph like we do for any other graph when using the dcc.Tooltip
but it seems to be not working or misaligned for Sankey figures.
Here’s the code to reproduce the above graph:
# imports
from dash import Dash, dcc, html, Output, Input, no_update
import plotly.graph_objects as go
# -----------------------------------------APP Definition---------------------------------------------------------------
app = Dash(__name__)
def genSankey():
fig = go.Figure(
data=[
go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=["A1", "A2", "B1", "B2", "C1", "C2"],
color="blue",
),
link=dict(
source=[
0,
1,
0,
2,
3,
3,
], # indices correspond to labels, eg A1, A2, A1, B1, ...
target=[2, 3, 3, 4, 4, 5],
value=[8, 4, 2, 8, 4, 2],
),
)
]
)
fig.update_traces(hoverinfo="none")
fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)
return fig
# -----------------------------------------APP Layout-------------------------------------------------------------------
app.layout = html.Div(
[dcc.Graph(id="sankey-graph", figure=genSankey()), dcc.Tooltip(id="graph-tooltip")],
)
# -----------------------------------------App Callback-------------------------------------------------------------------
@app.callback(
Output("graph-tooltip", "show"),
Output("graph-tooltip", "bbox"),
Output("graph-tooltip", "children"),
Input("sankey-graph", "hoverData")
)
def display_hover(hoverData):
if hoverData is None:
return False, no_update, no_update
print(hoverData, "\n")
# demo only shows the first point, but other points may also be available
pt = hoverData["points"][0]
try:
bbox = {"x0": pt["x0"], "x1": pt["x1"], "y0": pt["y0"], "y1": pt["y1"]}
except KeyError:
return False, no_update, no_update
children = [
html.Div(
[
html.P(f"x0: {pt['x0']}, x1: {pt['x1']:0.2f}"),
html.P(f"y0: {pt['y0']}, y1: {pt['y1']:0.2f}"),
],
style={"width": "200px", "white-space": "normal"},
)
]
return True, bbox, children
# -----------------------------------------Run Server-------------------------------------------------------------------
if __name__ == "__main__":
app.run_server(debug=True)