Merge p10-w1-resolution-slider into dev (P10 W1: fix zoom slider stacking-context occlusion)
This commit is contained in:
@@ -9,20 +9,25 @@
|
||||
|
||||
<div class="mix-waveform-bg">
|
||||
<canvas @ref="_canvas" class="mix-waveform-canvas"></canvas>
|
||||
|
||||
@* Viewing control only — never a seek surface. Hidden until a datum is present. *@
|
||||
@if (_hasDatum)
|
||||
{
|
||||
<div class="mix-waveform-zoom">
|
||||
<MudSlider T="double"
|
||||
Value="@ZoomFraction"
|
||||
ValueChanged="@OnZoomFractionChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Waveform zoom" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@* Viewing control only — never a seek surface. Hidden until a datum is present.
|
||||
Deliberately a SIBLING of .mix-waveform-bg, not a child: the backdrop is position:fixed and so
|
||||
forms its own stacking context, which would trap any descendant below the page's z-index:1
|
||||
foreground (.mix-detail-foreground) and let that foreground swallow the slider's pointer events.
|
||||
As a top-level sibling with its own z-index, the slider stacks above the foreground and stays
|
||||
draggable. *@
|
||||
@if (_hasDatum)
|
||||
{
|
||||
<div class="mix-waveform-zoom">
|
||||
<MudSlider T="double"
|
||||
Value="@ZoomFraction"
|
||||
ValueChanged="@OnZoomFractionChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Waveform zoom" />
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
private async Task OnZoomFractionChanged(double fraction)
|
||||
{
|
||||
ZoomState.VisibleSeconds = MixZoomMapping.FractionToSeconds(fraction);
|
||||
DebugLog($"zoom slider changed — raw fraction={fraction:F3} → visibleSeconds={ZoomState.VisibleSeconds:F3}s; pushing setZoom (handle={(_handle is null ? "null" : "ready")}).");
|
||||
await PushZoomAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@@ -21,13 +21,18 @@
|
||||
}
|
||||
|
||||
/* Zoom slider — a small viewing control pinned to the top-right, clear of the player bar at
|
||||
the bottom and the nav bar at the top. Pointer events are re-enabled here only (the backdrop
|
||||
stays inert), and it is never a seek surface. top: 5rem sits just below the fixed nav bar
|
||||
(~4.5rem tall) so neither the expanded player bar nor the nav occludes it. */
|
||||
the bottom and the nav bar at the top. It is never a seek surface. top: 5rem sits just below the
|
||||
fixed nav bar (~4.5rem tall) so neither the expanded player bar nor the nav occludes it.
|
||||
|
||||
position: fixed (not absolute) because the slider is now a top-level sibling of the backdrop, not
|
||||
a child of it — see the comment in the .razor. z-index: 10 lifts it above the page foreground
|
||||
(.mix-detail-foreground, z-index: 1) so the foreground can't intercept its pointer events; that
|
||||
occlusion was the resolution-slider regression. */
|
||||
.mix-waveform-zoom {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
right: 1.5rem;
|
||||
top: 5rem;
|
||||
z-index: 10;
|
||||
width: 180px;
|
||||
max-width: 40vw;
|
||||
pointer-events: auto;
|
||||
|
||||
@@ -795,7 +795,12 @@ export function create(canvas: HTMLCanvasElement): MixVisualizerHandle {
|
||||
setZoom(seconds: number): void {
|
||||
// Clamp into the supported span so a stray value can't break the math.
|
||||
visibleSeconds = Math.min(MAX_VISIBLE_SECONDS, Math.max(MIN_VISIBLE_SECONDS, seconds));
|
||||
if (!playback.isPlaying) redrawOnce();
|
||||
// While playing, the running rAF loop uploads uVisibleSeconds next frame; while idle the
|
||||
// loop is stopped (spec §E), so a zoom change must force one still frame here or the new
|
||||
// span is uploaded only on the next unrelated redraw (theme/datum/resize) — i.e. never.
|
||||
const idleRedraw = !playback.isPlaying;
|
||||
debugLog(`setZoom — requested ${seconds.toFixed(3)}s, clamped ${visibleSeconds.toFixed(3)}s; idleRedraw=${idleRedraw} (isPlaying=${playback.isPlaying}).`);
|
||||
if (idleRedraw) redrawOnce();
|
||||
},
|
||||
|
||||
refreshTheme(): void {
|
||||
|
||||
Reference in New Issue
Block a user