new interplot relations, elev_plot hovering position displays blue marker on line_map now

This commit is contained in:
2025-09-15 22:26:43 +02:00
parent 7129df8a79
commit efe3ff4be3

View File

@@ -14,7 +14,7 @@ import datetime
from math import radians, sin, cos, sqrt, asin
import dash
from dash import dcc, html, Input, Output, Dash
from dash import dcc, html, Input, Output, Dash, State
import dash_bootstrap_components as dbc
import pandas as pd
@@ -340,7 +340,7 @@ def create_info_banner(df):
'justifyContent': 'space-around',
'backgroundColor': '#1e1e1e',
'color': 'white',
'padding': '20px',
'padding': '5px',
'marginBottom': '5px',
'borderRadius': '10px',
'width': '100%',
@@ -355,25 +355,6 @@ def create_info_banner(df):
# START OF THE PLOTS
# =============================================================================
def create_map_plot(df):
# fig = px.line_map(
# df,
# lat='lat',
# lon='lon',
# hover_name='time',
# hover_data={
# 'cum_dist_km': ':.2f',
# 'duration_hms': True,
# 'lat': False,
# 'lon': False,
# 'time': False
# },
# labels={
# 'cum_dist_km': 'Distance (km) ',
# 'duration_hms': 'Elapsed Time '
# },
# zoom=13,
# height=800
# )
fig = px.line_map(
df,
lat='lat',
@@ -394,9 +375,9 @@ def create_map_plot(df):
customdata=df[['cum_dist_km', 'speed_kmh', 'heart_rate', 'duration_hms']]
)
# Define map style and the line ontop
fig.update_layout(map_style="open-street-map")
# The built-in plotly.js styles are: carto-darkmatter, carto-positron, open-street-map, stamen-terrain, stamen-toner, stamen-watercolor, white-bg
# The built-in Mapbox styles are: basic, streets, outdoors, light, dark, satellite, satellite-streets
fig.update_layout(map_style="open-street-map") #My-Fav: open-street-map, satellite-streets, dark, white-bg
# Possible Options:
# 'basic', 'carto-darkmatter', 'carto-darkmatter-nolabels', 'carto-positron', 'carto-positron-nolabels', 'carto-voyager', 'carto-voyager-nolabels', 'dark', 'light', 'open-street-map', 'outdoors', 'satellite', 'satellite-streets', 'streets', 'white-bg'.
fig.update_traces(line=dict(color="#f54269", width=3))
# Start / Stop marker
@@ -410,17 +391,33 @@ def create_map_plot(df):
lat=[end['lat']], lon=[end['lon']], mode='markers+text',
marker=dict(size=12, color='#b9fc62'), text=['Stop'], name='Stop', textposition='bottom left'
))
fig.update_layout(paper_bgcolor='#1e1e1e', font=dict(color='white'))
# THIS IS MY ELEVATION-PLOT SHOW POSITION-MARKER IN MAP-PLOT:
fig.add_trace(go.Scattermap(
lat=[],
lon=[],
mode="markers",
marker=dict(size=18, color="#42B1E5", symbol="circle"),
name="Hovered Point"
))
# KOMPAKTE LAYOUT-EINSTELLUNGEN
fig.update_layout(
legend=dict(
orientation='h', # horizontal layout
yanchor='top',
y=-0.01, # move legend below the map
xanchor='center',
x=0.5,
font=dict(color='white')
paper_bgcolor='#1e1e1e',
font=dict(color='white'),
# Margins reduzieren für kompakteren Plot
margin=dict(l=60, r=45, t=10, b=50), # Links, Rechts, Oben, Unten
# Plotly-Toolbar konfigurieren
showlegend=True,
# Kompakte Legend
legend=dict(
orientation='h', # horizontal layout
yanchor='top',
y=-0.02, # move legend below the map
xanchor='center',
x=0.5,
font=dict(color='white', size=10) # Kleinere Schrift
)
)
)
return fig
@@ -881,18 +878,20 @@ app.layout = html.Div([
)
def load_fit_data(path):
df = process_fit(path)
return df.to_json(date_format='iso', orient='split')
# Callback 2: Update All Plots
# Callback 2: Update All (static) Plots
@app.callback(
Output('info-banner', 'children'),
Output('fig-map', 'figure'),
Output('fig-map', 'figure', allow_duplicate=True),
Output('fig-elevation', 'figure'),
Output('fig_deviation', 'figure'),
Output('fig_speed', 'figure'),
Output('fig_hr', 'figure'),
Output('fig_pace_bars', 'figure'),
Input('stored-df', 'data')
Input('stored-df', 'data'),
prevent_initial_call=True
)
def update_all_plots(json_data):
df = pd.read_json(io.StringIO(json_data), orient='split')
@@ -908,6 +907,27 @@ def update_all_plots(json_data):
return info, fig_map, fig_elev, fig_dev, fig_speed, fig_hr, fig_pace
# Callback 3: Hover → update only hover (dynamic) marker
@app.callback(
Output('fig-map', 'figure'),
Input('fig-elevation', 'hoverData'),
State('fig-map', 'figure'),
State('stored-df', 'data'),
prevent_initial_call=True
)
def highlight_map(hoverData, fig_map, json_data):
df = pd.read_json(io.StringIO(json_data), orient='split')
if hoverData is not None:
point_index = hoverData['points'][0]['pointIndex']
lat, lon = df.iloc[point_index][['lat', 'lon']]
# update the last trace (the empty Hovered Point trace)
fig_map['data'][-1]['lat'] = [lat]
fig_map['data'][-1]['lon'] = [lon]
return fig_map
# === Run Server ===
if __name__ == '__main__':
app.run(debug=True, port=8051)