@using System.Globalization @if (_isDragging) {
}
@GetDisplayLabel()
@code { [Parameter] public double Value { get; set; } [Parameter] public EventCallback ValueChanged { get; set; } [Parameter] public double Min { get; set; } = 0; [Parameter] public double Max { get; set; } = 100; [Parameter] public double Step { get; set; } = 1; [Parameter] public string Label { get; set; } = ""; [Parameter] public int Size { get; set; } = 50; [Parameter] public MudBlazor.Color Color { get; set; } = MudBlazor.Color.Primary; [Parameter] public bool HoldValue { get; set; } = false; private bool _isDragging = false; private double _lastMouseY = 0; private double _dragValue = 0; private double GetNormalizedValue() { // Use drag value during dragging if HoldValue is enabled, otherwise use current Value double currentValue = (_isDragging && HoldValue) ? _dragValue : Value; return Math.Max(0, Math.Min(1, (currentValue - Min) / (Max - Min))); } private string GetDisplayLabel() { // Show drag value during dragging if HoldValue is enabled, otherwise use provided Label if (_isDragging && HoldValue) { return _dragValue.ToString("F0"); } return Label; } private string GetKnobColor() { return Color switch { MudBlazor.Color.Primary => "var(--mud-palette-primary)", MudBlazor.Color.Secondary => "var(--mud-palette-secondary)", MudBlazor.Color.Success => "var(--mud-palette-success)", MudBlazor.Color.Warning => "var(--mud-palette-warning)", MudBlazor.Color.Error => "var(--mud-palette-error)", MudBlazor.Color.Info => "var(--mud-palette-info)", _ => "var(--mud-palette-primary)" }; } private string GetBackgroundStrokeDashArray() { double circumference = 2 * Math.PI * 35; // radius = 35 double maxArc = circumference * 0.75; // 270 degrees return $"{maxArc} {circumference}"; } private string GetStrokeDashArray() { double circumference = 2 * Math.PI * 35; // radius = 35 double maxArc = circumference * 0.75; // 270 degrees double valueArc = maxArc * GetNormalizedValue(); return $"{valueArc} {circumference}"; } private string GetStrokeDashOffset() { // No offset needed - arc should start from the beginning and grow return "0"; } private string GetPointerX() { double angle = -225 + (270 * GetNormalizedValue()); // -225 to +45 degrees (centered on vertical) double radians = angle * Math.PI / 180; double x = 50 + (25 * Math.Cos(radians)); // radius = 25 for pointer return x.ToString("F1", CultureInfo.InvariantCulture); } private string GetPointerY() { double angle = -225 + (270 * GetNormalizedValue()); double radians = angle * Math.PI / 180; double y = 50 + (25 * Math.Sin(radians)); return y.ToString("F1", CultureInfo.InvariantCulture); } private async Task OnMouseDown(MouseEventArgs e) { _isDragging = true; _lastMouseY = e.ClientY; _dragValue = Value; // Initialize drag value with current value // Add global mouse event handlers using Blazor's event handling StateHasChanged(); } private async Task OnGlobalMouseMove(MouseEventArgs e) { if (_isDragging) { await UpdateValueFromMouse(e); } } private async Task OnGlobalMouseUp(MouseEventArgs e) { if (_isDragging && HoldValue) { // If HoldValue is enabled, emit the final value now if (Math.Abs(_dragValue - Value) > 0.001) { await ValueChanged.InvokeAsync(_dragValue); } } _isDragging = false; StateHasChanged(); } private async Task UpdateValueFromMouse(MouseEventArgs e) { // Calculate vertical delta from last mouse position double deltaY = _lastMouseY - e.ClientY; // Inverted: up = positive, down = negative _lastMouseY = e.ClientY; // Sensitivity factor (pixels to move for full range) double sensitivity = 100.0; // Calculate change in normalized value based on vertical movement double normalizedDelta = deltaY / sensitivity; double currentNormalized = GetNormalizedValue(); double newNormalized = Math.Max(0, Math.Min(1, currentNormalized + normalizedDelta)); // Convert to actual value double newValue = Min + (newNormalized * (Max - Min)); // Apply step if (Step > 0) { newValue = Math.Round(newValue / Step) * Step; } if (Math.Abs(newValue - (HoldValue ? _dragValue : Value)) > 0.001) // Avoid unnecessary updates { if (HoldValue) { // Update drag value only, don't emit ValueChanged yet _dragValue = newValue; StateHasChanged(); // Update visual only } else { // Original behavior - emit ValueChanged immediately Value = newValue; await ValueChanged.InvokeAsync(Value); } } } }