feat(mix): lava-lamp popover with RadialKnob controls + wider Mix detail body (P10 W4)
This commit is contained in:
@@ -2,71 +2,71 @@
|
||||
@using DeepDrftPublic.Client.Services
|
||||
@inject MixVisualizerControlState ControlState
|
||||
|
||||
@* The Mix visualizer controls row (Phase 10, Wave 2). Four continuous sliders — resolution,
|
||||
bubblyness, detach, color-shift speed — placed above the mix details and below the back button.
|
||||
This component owns NO JS interop: it mutates the shared, session-scoped MixVisualizerControlState
|
||||
and raises its Changed event. The backdrop bridge (MixWaveformVisualizer) subscribes to that event
|
||||
and pushes the affected uniform to the WebGL module. That keeps the JS module handle single-owned
|
||||
by the bridge and this component purely presentational. None of these is a seek surface (spec §D). *@
|
||||
@* The Mix visualizer controls (Phase 10, Wave 4). Four continuous RadialKnobs — resolution,
|
||||
bubblyness, detach, color-shift speed — laid out in a row. This component lives inside the
|
||||
lava-lamp popover on the Mix detail page (Wave 4 moved it out of the always-visible TopContent row).
|
||||
It owns NO JS interop: it mutates the shared, session-scoped MixVisualizerControlState and raises its
|
||||
Changed event. The backdrop bridge (MixWaveformVisualizer) subscribes to that event and pushes the
|
||||
affected uniform to the WebGL module. That keeps the JS module handle single-owned by the bridge and
|
||||
this component purely presentational. None of these is a seek surface (spec §D).
|
||||
|
||||
RadialKnob has no icon slot (its Label renders as SVG text), so each control's Material icon rides
|
||||
beside its knob as an adjacent MudIcon caption (spec §7e). HoldValue stays false so the knobs are
|
||||
live — ValueChanged fires continuously during drag, exactly as the sliders fired before, preserving
|
||||
the "visibly and continuously affects its target" feel and the Changed/NotifyChanged seam. *@
|
||||
|
||||
<div class="mix-visualizer-controls">
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
@* RadialKnob exposes no aria-label/attribute-capture and is out of scope to modify, so the
|
||||
accessible name rides on the wrapping group div instead (a plain element accepts it). *@
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Resolution (visible time-span)">
|
||||
<RadialKnob Value="@ResolutionFraction"
|
||||
ValueChanged="@OnResolutionChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.ZoomIn" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ResolutionFraction"
|
||||
ValueChanged="@OnResolutionChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Resolution (visible time-span)" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Bubblyness">
|
||||
<RadialKnob Value="@ControlState.Bubblyness"
|
||||
ValueChanged="@OnBubblynessChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.BubbleChart" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ControlState.Bubblyness"
|
||||
ValueChanged="@OnBubblynessChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Bubblyness" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Detach (unleash the lava lamp)">
|
||||
<RadialKnob Value="@ControlState.Detach"
|
||||
ValueChanged="@OnDetachChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Air" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ControlState.Detach"
|
||||
ValueChanged="@OnDetachChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Detach (unleash the lava lamp)" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Color-shift speed">
|
||||
<RadialKnob Value="@ControlState.ColorShiftSpeed"
|
||||
ValueChanged="@OnColorShiftSpeedChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Palette" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ControlState.ColorShiftSpeed"
|
||||
ValueChanged="@OnColorShiftSpeedChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Color-shift speed" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@code {
|
||||
// Resolution rides the log mapping (slider fraction [0,1] ↔ visible seconds); the other three are
|
||||
// Resolution rides the log mapping (knob fraction [0,1] ↔ visible seconds); the other three are
|
||||
// already normalized [0,1] and bind to their state properties directly.
|
||||
private double ResolutionFraction => MixZoomMapping.SecondsToFraction(ControlState.VisibleSeconds);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user