Merge p12-w4-t2-nowplaying into dev (12.D: real waveform visualizer in NowPlaying card, mode C + Fill mode)
This commit is contained in:
@@ -8,36 +8,22 @@
|
||||
: "Select a track to begin")
|
||||
</div>
|
||||
|
||||
@if (Player?.IsLoaded == true)
|
||||
{
|
||||
<div class="waveform-bars">
|
||||
@* 20 bars - approximate the wireframe's varied animation timings *@
|
||||
<div class="waveform-bar" style="--h-lo:6px;--h-hi:28px;--dur:0.7s;height:14px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:10px;--h-hi:36px;--dur:0.9s;height:28px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:4px;--h-hi:20px;--dur:0.65s;height:10px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:12px;--h-hi:40px;--dur:1.1s;height:36px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:6px;--h-hi:26px;--dur:0.8s;height:18px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:8px;--h-hi:32px;--dur:0.75s;height:24px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:4px;--h-hi:18px;--dur:0.95s;height:8px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:14px;--h-hi:42px;--dur:1.2s;height:32px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:6px;--h-hi:22px;--dur:0.68s;height:16px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:10px;--h-hi:38px;--dur:0.88s;height:30px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:4px;--h-hi:16px;--dur:0.72s;height:6px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:8px;--h-hi:30px;--dur:1.0s;height:20px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:12px;--h-hi:36px;--dur:0.85s;height:26px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:6px;--h-hi:24px;--dur:0.9s;height:14px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:10px;--h-hi:34px;--dur:0.78s;height:22px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:4px;--h-hi:20px;--dur:1.05s;height:12px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:14px;--h-hi:44px;--dur:0.92s;height:38px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:6px;--h-hi:26px;--dur:0.7s;height:18px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:8px;--h-hi:32px;--dur:0.82s;height:22px"></div>
|
||||
<div class="waveform-bar" style="--h-lo:4px;--h-hi:18px;--dur:1.15s;height:10px"></div>
|
||||
@* Mode C (§3f, §6c): the real waveform visualizer, contained to this card and driven by the live
|
||||
cascaded player. Fill="true" sizes the canvas to this positioned box instead of the viewport.
|
||||
The bridge follows whatever is playing — keyed on the current track via ReleaseEntryKey/TrackId/
|
||||
TrackEntryKey — so it scrolls to the real signal and sits at-rest when nothing plays. Read-only:
|
||||
the card visualizes, it never seeks. The lava-lamp popover sits in the corner (full parity, §8e). *@
|
||||
<div class="np-visualizer">
|
||||
<WaveformVisualizer Fill="true"
|
||||
ReleaseEntryKey="@(Player?.CurrentTrack?.Release?.EntryKey ?? string.Empty)"
|
||||
TrackId="@Player?.CurrentTrack?.Id"
|
||||
TrackEntryKey="@Player?.CurrentTrack?.EntryKey" />
|
||||
<div class="np-visualizer-controls">
|
||||
<WaveformVisualizerControlPopover IconSize="Size.Small"
|
||||
AnchorOrigin="Origin.BottomRight"
|
||||
TransformOrigin="Origin.TopLeft" />
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="waveform-placeholder"></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
@keyframes wave-dance {
|
||||
from { height: var(--h-lo, 4px); }
|
||||
to { height: var(--h-hi, 20px); }
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.3; }
|
||||
@@ -51,22 +46,25 @@
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
.waveform-bars {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
/* Contained visualizer region (Phase 12 mode C). The visualizer mounts with Fill="true", whose
|
||||
layer is `position: absolute; inset: 0` — so this box must be a positioned, sized ancestor for the
|
||||
canvas to fill. `overflow: hidden` keeps the lava inside the card's rounded chrome. The height is the
|
||||
card's bounded live readout — taller than the old synthetic-bar strip so the real waveform reads, but
|
||||
still compact for a home-page hero panel. */
|
||||
.np-visualizer {
|
||||
position: relative;
|
||||
height: 120px;
|
||||
margin-top: 1.2rem;
|
||||
}
|
||||
|
||||
.waveform-bar {
|
||||
width: 3px;
|
||||
background: var(--deepdrft-green-accent);
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
animation: wave-dance var(--dur, 1s) ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.waveform-placeholder {
|
||||
margin-top: 1.2rem;
|
||||
height: 1px;
|
||||
background: rgba(250, 250, 248, 0.12);
|
||||
}
|
||||
/* The lava-lamp popover trigger overlays the visualizer's top-right corner (full parity, §8e). Above
|
||||
the canvas (z-index) and pointer-enabled so the icon is clickable even though the canvas layer below
|
||||
it is pointer-events:none. */
|
||||
.np-visualizer-controls {
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
right: 0.25rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
scroll/zoom/compositing math live in the WaveformVisualizer.ts interop module; this component is a thin
|
||||
bridge that feeds it datum + playback + zoom + theme. Deliberately NOT the player-bar peak-bar idiom. *@
|
||||
|
||||
<div class="mix-waveform-bg">
|
||||
<div class="mix-waveform-bg @(Fill ? "mix-waveform-bg--fill" : null)">
|
||||
<canvas @ref="_canvas" class="mix-waveform-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -73,6 +73,17 @@ public partial class WaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
/// </summary>
|
||||
[Parameter] public double PlaybackPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Container-sizing mode (phase-12 §6c). Default <c>false</c> keeps the full-viewport mount the
|
||||
/// engine has always used (fixed, inset 0, clipped above the player bar) — Mix's mode-A full-bleed
|
||||
/// and the ambient mode-B mounts are unchanged. Set <c>true</c> for a contained mount (mode C, the
|
||||
/// NowPlaying card): the canvas fills its nearest positioned ancestor instead of the viewport, with
|
||||
/// no footer clip. This is a CSS/layout toggle only — the renderer already sizes the backing store to
|
||||
/// the canvas's own box (a ResizeObserver on the canvas, never <c>window</c>), so the JS module is
|
||||
/// identical in both modes; <c>Fill</c> only changes which box that canvas occupies.
|
||||
/// </summary>
|
||||
[Parameter] public bool Fill { get; set; }
|
||||
|
||||
// Bridge-level diagnostics. Mirrors the JS-side DEBUG flag in WaveformVisualizer.ts: when true the
|
||||
// datum-fetch / subscription / playback-coupling seams log to the browser console (prefixed
|
||||
// `[WaveformVisualizer]`, same as the JS logs so the two interleave into one timeline). These pinpoint
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Fill / container-sizing mode (Phase 12 §6c, mode C). The contained hosts (the NowPlaying card)
|
||||
set Fill="true": the canvas fills its nearest positioned ancestor instead of the viewport, and the
|
||||
footer clip drops (there is no player bar to clear — the bounding box IS the clip). The host is
|
||||
responsible for giving this layer a positioned, sized parent. `inset: 0` over `position: absolute`
|
||||
makes the box exactly that parent's content box; `overflow: hidden` still clips the canvas to it.
|
||||
The canvas backing-store sizing in WaveformVisualizer.ts is unchanged — it already measures the
|
||||
canvas's own box, so this purely re-parents the box from the viewport to the container. */
|
||||
.mix-waveform-bg--fill {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* The canvas fills the viewport. All ribbon shading (luminous depth, soft edges) is drawn inside the
|
||||
canvas by the WebGL2 fragment shader. NO CSS backdrop-filter: it was a confirmed per-frame perf killer
|
||||
on the Canvas predecessor and is exactly the cost the GPU move exists to eliminate (spec §2, §5.2);
|
||||
|
||||
Reference in New Issue
Block a user