It seems that the annotation text remains in the same size no matter we zoom in or out of a plot.
Is there a way to make annotation relative to zoom level, i.e it will be bigger when zoom-in, and smaller when zoom-out?
It seems that the annotation text remains in the same size no matter we zoom in or out of a plot.
Is there a way to make annotation relative to zoom level, i.e it will be bigger when zoom-in, and smaller when zoom-out?
Hi @oat ,
As far as i know, it can not be done if you using Plotly Python.
But it possible if you use Dash Plotly.
By using callback decorator, update font size of annotations text when zoom event triggered.
As callback input, I will use relayoutData
from Graph object , that contain data from latest relayout event which occurs when the user zooms or pans on the plot or other layout-level edits.
So from relayoutData
, when zoom in or zoom out, you can get current xaxis range.
Now you can set zoom-in/out percentage and multiply it by initial font size, to resize the font.
My suggestion solution will be
from dash import Dash,html,dcc,callback
import plotly.graph_objects as go
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
fig = go.Figure()
fig.add_trace({'x':[10,20,30,40,50],'y':[1,2,3,4,5]})
app = Dash(__name__)
app.layout=html.Div([
html.H1("Update Font Size of Annotations Text When Zoom"),
dcc.Graph(id='mygraph',figure=fig)
],style={"color": "orange"})
annotations = [
dict(xref='paper',x=0.5,y=3,
xanchor='left',yanchor='middle',
text='annotations text',
font=dict(size=16),
showarrow=False),
]
fig.update_layout(annotations=annotations)
@callback(
Output('mygraph','figure'),
Input('mygraph','relayoutData'),
State('mygraph','figure'))
def update_text_font(relayout_data, figure):
if relayout_data is None:
raise PreventUpdate
try:
x0 = relayout_data['xaxis.range[0]']
x1 = relayout_data['xaxis.range[1]']
# I set my initial range is from 0 to 50, so the delta is 50
zoom = round(50/(x1-x0),2)
# update font size
figure['layout']['annotations'][0]['font']['size']=int(16*zoom)
except KeyError:
raise PreventUpdate
return figure
if __name__ == "__main__":
app.run_server(host='0.0.0.0',port='8052')
``
Hope this help.
Thank you very much, @farispriadi. Your suggestion works like a charm.
Allow me to digest your solution and adopt it in my dash app.
Hi @farispriadi
May I ask two more questions?
How to put the original range, i.e. the value of 50 in your example, into the callback function, if this initial range may vary?
I tried to use figure[“layout”][“xaxis”][“range”] to get it, but what I got is the range after the zoom…
What is the third input parameter, i.e. component=“mygraph”, of the callback function?
I assume the first paramter, “relayout_data”, is related to Input, and the second one, “figure”, is related to State of the figure.
Thanks.
Hi @oat ,
As far as I know, there is no specific method to get initial range when you call figure[“layout”][“xaxis”][“range”]
inside callback function. Because, as you mentions, range has already change to current range after zoom .
The component
argument is actually not needed in update_text_font
function, this is purely my fault. So I have updated my suggestion solution. Thanks for asking questions.
Hope this answer your questions.