player bar: track changes morph shape into shape, not up from the dots
The arrival morph honestly started from whatever the lane showed — and on a track change the lane always showed dots, because the waveform empties the moment the queue moves. Every switch therefore played the same grow-from-zero, when the picked motion was one waveform transforming into another. A track change now HOLDS the outgoing shape for ARRIVE_HOLD_MS (600ms), painted in unplayed grey since the new track owns the transport. A quick arrival — a local file, a cached stream — lands inside the hold and the morph runs directly from the old bars into the new ones; a slow stream load falls to the dots-and-swell story when the hold expires, exactly as before. The rail mirrors the hold with the same shared constant, and suppresses the loading swell while holding so the keyframes cannot fight the held heights. Measured across a cached track switch: the lane's mean height never left 16.9-17.4 (the dots sit at 2, the old dip hit 5.2) while the per-column fingerprint changed — the shape transformed without ever falling.
This commit is contained in:
1 parent
1765de65cf
commit
0bbdb1bb0e
3 files changed
+68
-5
No files matched your search
@@ -38,6 +38,7 @@
|
||||
waveLevels,
|
||||
RISE_CADENCE_MS,
|
||||
ARRIVE_MS,
|
||||
ARRIVE_HOLD_MS,
|
||||
PENDING_ALPHA,
|
||||
} from "../lib/waveshape.js";
|
||||
|
||||
@@ -352,7 +353,15 @@
|
||||
const FLAT_BARS = $derived(Array(BARS).fill(0));
|
||||
const wavePending = $derived(bars.length === 0);
|
||||
const waveBars = $derived.by(() => {
|
||||
if (wavePending) return FLAT_BARS;
|
||||
if (wavePending) {
|
||||
// Mid-hold the outgoing shape is still the thing on screen.
|
||||
if (railHolding && lastRailBars?.length) {
|
||||
return lastRailBars.length >= BARS
|
||||
? lastRailBars
|
||||
: [...lastRailBars, ...Array(BARS - lastRailBars.length).fill(null)];
|
||||
}
|
||||
return FLAT_BARS;
|
||||
}
|
||||
if (bars.length >= BARS) return bars;
|
||||
return [...bars, ...Array(BARS - bars.length).fill(null)];
|
||||
});
|
||||
@@ -390,13 +399,37 @@
|
||||
}, RISE_CADENCE_MS);
|
||||
return () => clearInterval(timer);
|
||||
});
|
||||
// Track-change hold — the playbar's ARRIVE_HOLD_MS, mirrored: the
|
||||
// outgoing bars stay up briefly so a quick arrival transitions
|
||||
// shape→shape instead of dropping to the floor first. The hold renders in
|
||||
// full-opacity muted (the new track owns the transport, nothing played);
|
||||
// a slow load falls to the pending dots when the timer expires.
|
||||
let lastRailBars = null;
|
||||
let railHolding = $state(false);
|
||||
let railHoldTimer = null;
|
||||
$effect(() => {
|
||||
if (bars.length > 0) {
|
||||
lastRailBars = bars;
|
||||
railHolding = false;
|
||||
clearTimeout(railHoldTimer);
|
||||
} else if (player.wavePending && lastRailBars?.length) {
|
||||
railHolding = true;
|
||||
clearTimeout(railHoldTimer);
|
||||
railHoldTimer = setTimeout(() => (railHolding = false), ARRIVE_HOLD_MS);
|
||||
}
|
||||
});
|
||||
$effect(() => () => clearTimeout(railHoldTimer));
|
||||
|
||||
function railBarHeight(v, i) {
|
||||
if (wavePending || v == null) return 0;
|
||||
if (v == null) return 0;
|
||||
if (wavePending) return railHolding ? barHeight(v) : 0;
|
||||
if (railRising && i >= railRevealed) return 0;
|
||||
return barHeight(v);
|
||||
}
|
||||
function railBarDim(v, i) {
|
||||
return wavePending || v == null || (railRising && i >= railRevealed);
|
||||
if (v == null) return true;
|
||||
if (wavePending) return !railHolding;
|
||||
return railRising && i >= railRevealed;
|
||||
}
|
||||
|
||||
// The arrival morph — the playbar's M2, in CSS: when a COMPLETE waveform
|
||||
@@ -1103,7 +1136,7 @@
|
||||
class="wave"
|
||||
class:scrubbing={waveDragging}
|
||||
class:pending={wavePending}
|
||||
class:loading={wavePending && player.wavePending}
|
||||
class:loading={wavePending && player.wavePending && !railHolding}
|
||||
class:rising={railRising}
|
||||
class:arriving={railArriving}
|
||||
style="--bar-gap: {BAR_PITCH - BAR_W}px; --bars: {waveBars.length}"
|
||||
|
||||
Reference in new issue
Block a user