| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- using Avalonia;
- using Avalonia.Controls;
- using Avalonia.Media;
- using Avalonia.Threading;
- using System;
- using System.Globalization;
- namespace YZWater.Avalonia.Controls;
- public class FanControl : Control
- {
- public static readonly StyledProperty<bool> IsRunningProperty = AvaloniaProperty.Register<FanControl, bool>(nameof(IsRunning), false);
- public static readonly StyledProperty<double> SpeedProperty = AvaloniaProperty.Register<FanControl, double>(nameof(Speed), 1.0);
- public static readonly StyledProperty<string> TextProperty = AvaloniaProperty.Register<FanControl, string>(nameof(Text), "Fan");
- public bool IsRunning { get => GetValue(IsRunningProperty); set => SetValue(IsRunningProperty, value); }
- public double Speed { get => GetValue(SpeedProperty); set => SetValue(SpeedProperty, value); }
- public string Text { get => GetValue(TextProperty); set => SetValue(TextProperty, value); }
- private double _angle;
- private IDisposable? _timer;
- static FanControl() { AffectsRender<FanControl>(IsRunningProperty, SpeedProperty, TextProperty); }
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
- {
- base.OnAttachedToVisualTree(e);
- ThemeHelper.ThemeChanged += OnThemeChanged;
- if (IsRunning) StartAnim();
- }
- protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
- {
- ThemeHelper.ThemeChanged -= OnThemeChanged;
- StopAnim();
- base.OnDetachedFromVisualTree(e);
- }
- private void OnThemeChanged() => InvalidateVisual();
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
- {
- base.OnPropertyChanged(change);
- if (change.Property == IsRunningProperty) { if (IsRunning) StartAnim(); else { StopAnim(); _angle = 0; } }
- }
- private void StartAnim() { StopAnim(); _timer = DispatcherTimer.Run(() => { _angle += Speed * 2; if (_angle >= 360) _angle -= 360; InvalidateVisual(); return true; }, TimeSpan.FromMilliseconds(50)); }
- private void StopAnim() { _timer?.Dispose(); _timer = null; }
- 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;
- var radius = Math.Min(bounds.Width, bounds.Height) / 2 - 5;
- var typeface = new Typeface("Microsoft YaHei", FontStyle.Normal, FontWeight.Bold);
- var fanColor = IsRunning ? ThemeHelper.Success : ThemeHelper.TextDisabled;
- context.DrawRectangle(null, new Pen(ThemeHelper.Border, 2), new Rect(cx - radius, cy - radius, radius * 2, radius * 2));
- for (int i = 0; i < 4; i++)
- {
- var angle = _angle + 90.0 * i;
- var bx = cx + Math.Cos(angle * Math.PI / 180) * radius * 0.8 * 0.4;
- var by = cy + Math.Sin(angle * Math.PI / 180) * radius * 0.8 * 0.4;
- context.DrawRectangle(fanColor, null, new Rect(bx - radius * 0.125, by - radius * 0.4, radius * 0.25, radius * 0.8));
- }
- var cr = radius * 0.15;
- context.DrawEllipse(fanColor, null, new Rect(cx - cr, cy - cr, cr * 2, cr * 2));
- if (!string.IsNullOrEmpty(Text))
- {
- var t = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 10, ThemeHelper.TextPrimary);
- context.DrawText(t, new Point(cx - t.Width / 2, bounds.Bottom - t.Height - 2));
- }
- }
- protected override Size MeasureOverride(Size availableSize) => new Size(50, 50);
- }
|