fix elevation_gain_m null for modern Garmin FIT files; fix map flash
FIT parser: try enhanced_altitude before altitude. Barometric altimeters on modern Garmins (Edge 540, 840, etc.) write enhanced_altitude in record messages and total_ascent in lap messages. The old code read only altitude, producing null elevation_m per point → null elevation_gain_m at the activity root while laps had correct values from total_ascent. ActivityMap: use preview_coords (passed from ActivitySummary) to initialise the map at the activity's location on mount, eliminating the flash of world-view before the async detail JSON / bbox arrives.
This commit is contained in:
@@ -57,12 +57,17 @@ class FitParser:
|
|||||||
lat = _semicircles_to_deg(_get(frame, "position_lat"))
|
lat = _semicircles_to_deg(_get(frame, "position_lat"))
|
||||||
lon = _semicircles_to_deg(_get(frame, "position_long"))
|
lon = _semicircles_to_deg(_get(frame, "position_long"))
|
||||||
speed_raw = _get(frame, "speed") # m/s
|
speed_raw = _get(frame, "speed") # m/s
|
||||||
|
# enhanced_altitude is written by barometric altimeters (most
|
||||||
|
# modern Garmins). Fall back to GPS-derived altitude if absent.
|
||||||
|
_alt = _get(frame, "enhanced_altitude")
|
||||||
|
if _alt is None:
|
||||||
|
_alt = _get(frame, "altitude")
|
||||||
|
|
||||||
dp = DataPoint(
|
dp = DataPoint(
|
||||||
timestamp=ts,
|
timestamp=ts,
|
||||||
lat=lat,
|
lat=lat,
|
||||||
lon=lon,
|
lon=lon,
|
||||||
elevation_m=_get(frame, "altitude"),
|
elevation_m=_alt,
|
||||||
hr_bpm=_get(frame, "heart_rate"),
|
hr_bpm=_get(frame, "heart_rate"),
|
||||||
cadence_rpm=_get(frame, "cadence"),
|
cadence_rpm=_get(frame, "cadence"),
|
||||||
speed_kmh=speed_raw * 3.6 if speed_raw is not None else None,
|
speed_kmh=speed_raw * 3.6 if speed_raw is not None else None,
|
||||||
|
|||||||
@@ -244,6 +244,7 @@
|
|||||||
{trackUrl}
|
{trackUrl}
|
||||||
{timeseries}
|
{timeseries}
|
||||||
bbox={detail?.bbox ?? null}
|
bbox={detail?.bbox ?? null}
|
||||||
|
initialCoords={activity.preview_coords}
|
||||||
accentColor={color}
|
accentColor={color}
|
||||||
bind:hoveredIdx
|
bind:hoveredIdx
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
export let trackUrl: string;
|
export let trackUrl: string;
|
||||||
export let timeseries: Timeseries | null = null;
|
export let timeseries: Timeseries | null = null;
|
||||||
export let bbox: [number, number, number, number] | null = null;
|
export let bbox: [number, number, number, number] | null = null;
|
||||||
|
/** ~20 [lat, lon] preview coords from the activity summary — used to position
|
||||||
|
* the map immediately on mount so there's no flash of world view before the
|
||||||
|
* detail JSON loads and bbox arrives. */
|
||||||
|
export let initialCoords: [number, number][] | null = null;
|
||||||
export let accentColor: string = '#00c8ff';
|
export let accentColor: string = '#00c8ff';
|
||||||
export let hoveredIdx: number | null = null;
|
export let hoveredIdx: number | null = null;
|
||||||
|
|
||||||
@@ -19,11 +23,25 @@
|
|||||||
const TILE_STYLE = 'https://tiles.openfreemap.org/styles/positron';
|
const TILE_STYLE = 'https://tiles.openfreemap.org/styles/positron';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
// Derive initial center and zoom from preview_coords so the map starts at
|
||||||
|
// the right location without waiting for the async detail JSON / bbox load.
|
||||||
|
let initCenter: [number, number] = [0, 0];
|
||||||
|
let initZoom = 1;
|
||||||
|
if (initialCoords && initialCoords.length > 0) {
|
||||||
|
const lats = initialCoords.map(c => c[0]);
|
||||||
|
const lons = initialCoords.map(c => c[1]);
|
||||||
|
initCenter = [
|
||||||
|
(Math.min(...lons) + Math.max(...lons)) / 2,
|
||||||
|
(Math.min(...lats) + Math.max(...lats)) / 2,
|
||||||
|
];
|
||||||
|
initZoom = 10; // rough default; fitBounds will correct this when bbox arrives
|
||||||
|
}
|
||||||
|
|
||||||
map = new maplibregl.Map({
|
map = new maplibregl.Map({
|
||||||
container: mapEl,
|
container: mapEl,
|
||||||
style: TILE_STYLE,
|
style: TILE_STYLE,
|
||||||
center: [0, 0],
|
center: initCenter,
|
||||||
zoom: 1,
|
zoom: initZoom,
|
||||||
attributionControl: false,
|
attributionControl: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user