Hello @Zic ,
Here, check this out:
from dash import *
import pandas as pd
import plotly.express as px
import dash_bootstrap_components as dbc
import json
data = {
"x": [1,2,3,4,5],
"y": [1,2,3,4,5],
"time": [1,2,3,4,5]
}
df = pd.DataFrame(data)
app = Dash(external_stylesheets=[dbc.themes.SLATE])
app.layout = html.Div([
html.Div(
className="app-header",
children=[
html.H1('Overview of the DashBoard', className="app-header--title"),
html.Button(id='syncData', style={'display': 'none'}),
dcc.Graph(id ="myfig",figure = px.scatter(df, x='x', y='y', animation_frame="time", range_x=[0,5], range_y=[0,5])),
dcc.Store(id='currentFrame', storage_type='local', data=0),
html.Div(id='toShow')
]
)])
app.clientside_callback(
"""
async function (graph, target) {
var myGraph = document.querySelector(`#${graph} .js-plotly-plot`)
const delay = ms => new Promise(res => setTimeout(res, ms));
while (!myGraph) {
await delay(100)
myGraph = document.querySelector(`#${graph} .js-plotly-plot`)
}
myGraph.on('plotly_animated', () => {
localStorage.setItem(target, myGraph.layout.sliders[0].active)
document.querySelector('#syncData').click()
})
return window.dash_clientside.no_update
}
""",
Output("currentFrame", "id"),
Input("myfig", "id"),
State("currentFrame", "id"),
)
app.clientside_callback(
"""
function (n, store) {
return localStorage.getItem(store)
}
""",
Output('currentFrame', 'data'),
Input('syncData', 'n_clicks'),
State("currentFrame", "id"),
prevent_initial_call=True
)
@app.callback(
Output('toShow', 'children'),
Input('currentFrame', 'data'),
State("myfig", "figure"),
)
def toShow(d, fig):
return html.Div([
d,
'-- data --',
json.dumps(fig['frames'][int(d)])
], style={'padding': '10px'})
if __name__ == '__main__' :
app.run_server(debug=True)
This adds a custom event listener on the underlying plotly div, this will trigger and pull the data based upon the current frame when the animation is stopped.
The other callbacks are all to sync the data… Hopefully soon, Dash will allow JS functions to update the properties directly.