So I have this simple python dash application in which I've laid out a graph and a button. My goal is this: when I press the button, I want to retrieve the shapes that have been drawn.
import plotly.graph_objects as go
import dash
from dash import html, dcc, Input, Output, State
app = dash.Dash(__name__)
fig = go.Figure()
app.layout = html.Div([
dcc.Graph(id = "graph-pic", className="graph-pic", figure=fig, config={'modeBarButtonsToAdd':['drawrect', 'eraseshape']}),
html.Button("Shape count", id = "shape-count-button")
])
fig.add_shape(editable=True, x0=-1, x1=0, y0=2, y1=3, xref='x', yref='y')
@app.callback(
Output("graph-pic", "figure"),
Input("shape-count-button", "n_clicks")
)
def on_shape_count_button_pressed(n_clicks):
trigger_id = dash.callback_context.triggered_id
if trigger_id == "shape-count-button":
print("Shape count: " + str(len(fig.layout.shapes)))
print(fig.layout.shapes)
return dash.no_update
if __name__ == "__main__":
app.run_server()
When I press the button, it only prints the first shape that I've added through code... and NOT the ones that I've drawn on the graph with the draw rectangle tool.
Output:
Shape count: 1
(layout.Shape({
'editable': True, 'x0': -1, 'x1': 0, 'xref': 'x', 'y0': 2, 'y1': 3, 'yref': 'y'
}),)
Any hint would be appreciated!
You should use relayout_data
to detect all the drawn shapes on the graph, and then you can parse the desired data as you would:
import dash
import json
import plotly.graph_objects as go
from dash import html, dcc, Input, Output, State
app = dash.Dash(__name__)
fig = go.Figure()
app.layout = html.Div([
dcc.Graph(id = "graph-pic", className="graph-pic", figure=fig, config={'modeBarButtonsToAdd':['drawrect', 'eraseshape']}),
html.Button("Shape count", id = "shape-count-button"),
html.Div(id="text")
])
fig.add_shape(editable=True, x0=-1, x1=0, y0=2, y1=3, xref='x', yref='y')
@app.callback(
Output("text", "children"),
Input("shape-count-button", "n_clicks"),
Input("graph-pic", "relayoutData"),
)
def on_shape_count_button_pressed(n_clicks, relayout_data):
trigger_id = dash.callback_context.triggered_id
if trigger_id == "shape-count-button":
text_lst = "Shape count: " + str(len(fig.layout.shapes))
text_lst += str(fig.layout.shapes)
if "shapes" in relayout_data:
text_lst += json.dumps(relayout_data["shapes"], indent=2)
return text_lst
return dash.no_update
if __name__ == "__main__":
app.run_server()