|
@@ -8,6 +8,7 @@ const Elevation = (() => {
|
|
|
let chartPts = null; // downsampled
|
|
let chartPts = null; // downsampled
|
|
|
let bounds = null; // computed after draw: {cw,ch,minE,eRange,totDist}
|
|
let bounds = null; // computed after draw: {cw,ch,minE,eRange,totDist}
|
|
|
let trackMeta = null; // {name, trackDate, ...} from the track's meta
|
|
let trackMeta = null; // {name, trackDate, ...} from the track's meta
|
|
|
|
|
+ let elevStats = null; // {gain, loss} computed from full-res points
|
|
|
|
|
|
|
|
// ===== Public API =====
|
|
// ===== Public API =====
|
|
|
|
|
|
|
@@ -25,11 +26,12 @@ const Elevation = (() => {
|
|
|
trackMeta = meta || null;
|
|
trackMeta = meta || null;
|
|
|
chartPts = downsample(pts, CHART_MAX_PTS);
|
|
chartPts = downsample(pts, CHART_MAX_PTS);
|
|
|
bounds = null;
|
|
bounds = null;
|
|
|
|
|
+ elevStats = computeElevStats(pts);
|
|
|
raf(draw);
|
|
raf(draw);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function clear() {
|
|
function clear() {
|
|
|
- points = chartPts = bounds = trackMeta = null;
|
|
|
|
|
|
|
+ points = chartPts = bounds = trackMeta = elevStats = null;
|
|
|
hideTooltip();
|
|
hideTooltip();
|
|
|
if (canvas) {
|
|
if (canvas) {
|
|
|
canvas.width = canvas.width; // reset context
|
|
canvas.width = canvas.width; // reset context
|
|
@@ -91,6 +93,19 @@ const Elevation = (() => {
|
|
|
return out;
|
|
return out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ function computeElevStats(pts) {
|
|
|
|
|
+ let gain = 0, loss = 0, prev = null;
|
|
|
|
|
+ for (const p of pts) {
|
|
|
|
|
+ if (p.ele == null) continue;
|
|
|
|
|
+ if (prev != null) {
|
|
|
|
|
+ const d = p.ele - prev;
|
|
|
|
|
+ if (d > 0) gain += d; else loss -= d;
|
|
|
|
|
+ }
|
|
|
|
|
+ prev = p.ele;
|
|
|
|
|
+ }
|
|
|
|
|
+ return { gain: Math.round(gain), loss: Math.round(loss) };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// ===== Chart drawing =====
|
|
// ===== Chart drawing =====
|
|
|
|
|
|
|
|
function draw() {
|
|
function draw() {
|
|
@@ -125,6 +140,7 @@ const Elevation = (() => {
|
|
|
|
|
|
|
|
drawGrid(ctx, rect, cw, ch, minE, maxE, eRange, totDist);
|
|
drawGrid(ctx, rect, cw, ch, minE, maxE, eRange, totDist);
|
|
|
drawProfile(ctx, cw, ch, minE, eRange, totDist);
|
|
drawProfile(ctx, cw, ch, minE, eRange, totDist);
|
|
|
|
|
+ if (elevStats) drawStats(ctx, cw);
|
|
|
|
|
|
|
|
bounds = { cw, ch, minE, maxE, eRange, totDist };
|
|
bounds = { cw, ch, minE, maxE, eRange, totDist };
|
|
|
}
|
|
}
|
|
@@ -191,6 +207,14 @@ const Elevation = (() => {
|
|
|
ctx.stroke();
|
|
ctx.stroke();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ function drawStats(ctx, cw) {
|
|
|
|
|
+ const text = `▲ ${elevStats.gain} m ▼ ${elevStats.loss} m`;
|
|
|
|
|
+ ctx.font = '10px sans-serif';
|
|
|
|
|
+ ctx.textAlign = 'right';
|
|
|
|
|
+ ctx.fillStyle = 'rgba(120,120,120,0.9)';
|
|
|
|
|
+ ctx.fillText(text, PAD.left + cw - 2, PAD.top + 10);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// Draw a vertical cursor + dot at the given point (CSS pixel coords)
|
|
// Draw a vertical cursor + dot at the given point (CSS pixel coords)
|
|
|
function drawIndicator(point) {
|
|
function drawIndicator(point) {
|
|
|
if (!bounds || !canvas) return;
|
|
if (!bounds || !canvas) return;
|