| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- using Avalonia;
- using Avalonia.Controls;
- using Avalonia.Media;
- using System;
- using System.Globalization;
- namespace YZWater.Avalonia.Controls;
- public class GaugeControl : Control
- {
- public static readonly StyledProperty<double> ValueProperty = AvaloniaProperty.Register<GaugeControl, double>(nameof(Value), 0.0);
- public static readonly StyledProperty<double> MinValueProperty = AvaloniaProperty.Register<GaugeControl, double>(nameof(MinValue), 0.0);
- public static readonly StyledProperty<double> MaxValueProperty = AvaloniaProperty.Register<GaugeControl, double>(nameof(MaxValue), 100.0);
- public static readonly StyledProperty<string> TitleProperty = AvaloniaProperty.Register<GaugeControl, string>(nameof(Title), "Flow");
- public static readonly StyledProperty<string> UnitProperty = AvaloniaProperty.Register<GaugeControl, string>(nameof(Unit), "m鲁/h");
- public static readonly StyledProperty<IBrush> ValueColorProperty = AvaloniaProperty.Register<GaugeControl, IBrush>(nameof(ValueColor));
- public double Value { get => GetValue(ValueProperty); set => SetValue(ValueProperty, value); }
- public double MinValue { get => GetValue(MinValueProperty); set => SetValue(MinValueProperty, value); }
- public double MaxValue { get => GetValue(MaxValueProperty); set => SetValue(MaxValueProperty, value); }
- public string Title { get => GetValue(TitleProperty); set => SetValue(TitleProperty, value); }
- public string Unit { get => GetValue(UnitProperty); set => SetValue(UnitProperty, value); }
- public IBrush ValueColor { get => GetValue(ValueColorProperty); set => SetValue(ValueColorProperty, value); }
- static GaugeControl() { AffectsRender<GaugeControl>(ValueProperty, MinValueProperty, MaxValueProperty, TitleProperty, UnitProperty, ValueColorProperty); }
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); ThemeHelper.ThemeChanged += OnThemeChanged; }
- protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) { ThemeHelper.ThemeChanged -= OnThemeChanged; base.OnDetachedFromVisualTree(e); }
- private void OnThemeChanged() => InvalidateVisual();
- public override void Render(DrawingContext context)
- {
- base.Render(context);
- var bounds = new Rect(Bounds.Size);
- var cx = bounds.Width / 2; var cy = bounds.Height / 2 + 10;
- var radius = Math.Min(bounds.Width, bounds.Height) / 2 - 20;
- var typeface = new Typeface("Microsoft YaHei", FontStyle.Normal, FontWeight.Bold);
- context.DrawEllipse(ThemeHelper.PanelBg, null, new Rect(cx - radius - 5, cy - radius - 5, (radius + 5) * 2, (radius + 5) * 2));
- DrawArc(context, new Pen(ThemeHelper.Border, 8), cx, cy, radius, 135, 270);
- var normalized = Math.Max(0, Math.Min(1, (Value - MinValue) / (MaxValue - MinValue)));
- var valueAngle = 135 + normalized * 270;
- var valueColor = ValueColor ?? ThemeHelper.Success;
- DrawArc(context, new Pen(valueColor, 8), cx, cy, radius, 135, valueAngle - 135);
- for (int i = 0; i <= 10; i++)
- {
- var angle = 135 + (270.0 * i / 10);
- var rad = angle * Math.PI / 180;
- var isMajor = i % 5 == 0;
- var tickLen = isMajor ? 12 : 6;
- context.DrawLine(new Pen(isMajor ? ThemeHelper.TextPrimary : ThemeHelper.TextDisabled, isMajor ? 2 : 1),
- new Point(cx + Math.Cos(rad) * (radius - tickLen), cy + Math.Sin(rad) * (radius - tickLen)),
- new Point(cx + Math.Cos(rad) * radius, cy + Math.Sin(rad) * radius));
- }
- var pAngle = valueAngle * Math.PI / 180;
- var pLen = radius * 0.7;
- context.DrawLine(new Pen(valueColor, 3), new Point(cx, cy), new Point(cx + Math.Cos(pAngle) * pLen, cy + Math.Sin(pAngle) * pLen));
- context.DrawEllipse(valueColor, null, new Rect(cx - 6, cy - 6, 12, 12));
- var titleText = new FormattedText(Title, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12, ThemeHelper.TextPrimary);
- context.DrawText(titleText, new Point(cx - titleText.Width / 2, bounds.Y + 5));
- var valText = new FormattedText($"{Value:F1}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Microsoft YaHei", FontStyle.Normal, FontWeight.Bold), 20, ThemeHelper.TextPrimary);
- context.DrawText(valText, new Point(cx - valText.Width / 2, cy + radius * 0.3));
- var unitText = new FormattedText(Unit, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 10, ThemeHelper.TextDisabled);
- context.DrawText(unitText, new Point(cx - unitText.Width / 2, cy + radius * 0.3 + valText.Height + 2));
- }
- private void DrawArc(DrawingContext context, IPen pen, double cx, double cy, double radius, double startAngle, double sweepAngle)
- {
- var startRad = startAngle * Math.PI / 180;
- var endRad = (startAngle + sweepAngle) * Math.PI / 180;
- var steps = 36;
- var px = cx + Math.Cos(startRad) * radius;
- var py = cy + Math.Sin(startRad) * radius;
- for (int i = 1; i <= steps; i++)
- {
- var t = (double)i / steps;
- var angle = startRad + (endRad - startRad) * t;
- var x = cx + Math.Cos(angle) * radius;
- var y = cy + Math.Sin(angle) * radius;
- context.DrawLine(pen, new Point(px, py), new Point(x, y));
- px = x; py = y;
- }
- }
- protected override Size MeasureOverride(Size availableSize) => new Size(120, 140);
- }
|