Rate monitor: peak-hold tick on the equalizer bars (the VU idiom)
A thin accent marker sticks at each bar's recent maximum, holds ~1.2s, then falls a few percent per update until it rests on the live fill — exactly how a hardware VU meter's peak LED behaves. A traffic burst stays readable for a few seconds after it's over instead of vanishing with the next 1s sample. Hidden while it sits on the fill so idle bars don't carry a stray line.
This commit is contained in:
parent
01ae63f0d5
commit
12ad373a83
2 changed files with 45 additions and 1 deletions
|
|
@ -236,6 +236,7 @@ function _renderEqualizerBars(grid, data) {
|
|||
<div class="rate-eq-shimmer"></div>
|
||||
<div class="rate-eq-tip"></div>
|
||||
</div>
|
||||
<div class="rate-eq-peak"></div>
|
||||
<div class="rate-eq-value">0</div>
|
||||
</div>
|
||||
<div class="rate-eq-meta">
|
||||
|
|
@ -275,6 +276,26 @@ function _renderEqualizerBars(grid, data) {
|
|||
const fill = bar.querySelector('.rate-eq-fill');
|
||||
if (fill) fill.style.height = `${pct * 100}%`;
|
||||
|
||||
// Peak-hold tick — the VU-meter idiom: a thin marker sticks at the
|
||||
// recent maximum, holds ~1.2s, then falls a few %/update until it
|
||||
// rests on the live fill. A burst stays readable after it's over.
|
||||
const nowTs = performance.now();
|
||||
let peak = prev.peak ?? pct;
|
||||
let peakAt = prev.peakAt ?? nowTs;
|
||||
if (pct >= peak) {
|
||||
peak = pct;
|
||||
peakAt = nowTs;
|
||||
} else if (nowTs - peakAt > 1200) {
|
||||
peak = Math.max(pct, peak - 0.045);
|
||||
}
|
||||
const peakEl = bar.querySelector('.rate-eq-peak');
|
||||
if (peakEl) {
|
||||
peakEl.style.bottom = `${peak * 100}%`;
|
||||
// Only show while meaningfully above the live fill — idle bars
|
||||
// shouldn't carry a stray line.
|
||||
peakEl.classList.toggle('visible', peak > pct + 0.015 && peak > 0.06);
|
||||
}
|
||||
|
||||
// The reflection puddle (CSS ::after on the track) fades in
|
||||
// proportional to the real (unclamped) rate so idle services
|
||||
// don't pollute the row with a floor of glow. Bound to a
|
||||
|
|
@ -329,7 +350,7 @@ function _renderEqualizerBars(grid, data) {
|
|||
bar.classList.toggle('active', value > 0 || wStatus === 'running');
|
||||
bar.classList.toggle('rate-limited', isRateLimited);
|
||||
|
||||
_eqDisplay[svc] = { value, pct };
|
||||
_eqDisplay[svc] = { value, pct, peak, peakAt };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63242,6 +63242,29 @@ body.reduce-effects .dash-card::after {
|
|||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* Peak-hold tick — sticks at the recent maximum and slowly falls, like a
|
||||
* hardware VU meter's peak LED. Position (bottom %) is driven from JS;
|
||||
* only visible while it's meaningfully above the live fill so idle bars
|
||||
* don't carry a stray line. */
|
||||
.rate-eq-peak {
|
||||
position: absolute;
|
||||
left: 10%;
|
||||
right: 10%;
|
||||
bottom: 4%;
|
||||
height: 2px;
|
||||
border-radius: 1px;
|
||||
background: color-mix(in srgb, var(--eq-accent) 55%, white 45%);
|
||||
box-shadow: 0 0 6px color-mix(in srgb, var(--eq-accent) 70%, transparent);
|
||||
opacity: 0;
|
||||
transition: bottom 0.9s linear, opacity 0.4s;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.rate-eq-peak.visible {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* Vertical shimmer scan — runs continuously when active */
|
||||
.rate-eq-shimmer {
|
||||
position: absolute;
|
||||
|
|
|
|||
Loading…
Reference in a new issue