using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Threading;
using System;
using System.Globalization;
namespace YZWater.Avalonia.Controls;
///
/// 泵控件 - 模拟 HslPumpOne(优化版)
///
public class PumpControl : Control
{
public static readonly StyledProperty IsRunningProperty =
AvaloniaProperty.Register(nameof(IsRunning), false);
public static readonly StyledProperty SpeedProperty =
AvaloniaProperty.Register(nameof(Speed), 0.0);
public static readonly StyledProperty FrequencyProperty =
AvaloniaProperty.Register(nameof(Frequency), 50.0);
public static readonly StyledProperty TextProperty =
AvaloniaProperty.Register(nameof(Text), string.Empty);
public static readonly StyledProperty RunningColorProperty =
AvaloniaProperty.Register(nameof(RunningColor), new SolidColorBrush(Color.Parse("#4CAF50")));
public static readonly StyledProperty StoppedColorProperty =
AvaloniaProperty.Register(nameof(StoppedColor), new SolidColorBrush(Color.Parse("#607D8B")));
public static readonly StyledProperty FaultColorProperty =
AvaloniaProperty.Register(nameof(FaultColor), new SolidColorBrush(Color.Parse("#F44336")));
public bool IsRunning
{
get => GetValue(IsRunningProperty);
set => SetValue(IsRunningProperty, value);
}
public double Speed
{
get => GetValue(SpeedProperty);
set => SetValue(SpeedProperty, value);
}
public double Frequency
{
get => GetValue(FrequencyProperty);
set => SetValue(FrequencyProperty, value);
}
public string Text
{
get => GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public IBrush RunningColor
{
get => GetValue(RunningColorProperty);
set => SetValue(RunningColorProperty, value);
}
public IBrush StoppedColor
{
get => GetValue(StoppedColorProperty);
set => SetValue(StoppedColorProperty, value);
}
public IBrush FaultColor
{
get => GetValue(FaultColorProperty);
set => SetValue(FaultColorProperty, value);
}
private double _rotationAngle = 0;
private IDisposable? _timerSubscription;
static PumpControl()
{
AffectsRender(IsRunningProperty, SpeedProperty, FrequencyProperty,
TextProperty, RunningColorProperty, StoppedColorProperty, FaultColorProperty);
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if (IsRunning)
{
StartAnimation();
}
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
StopAnimation();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsRunningProperty)
{
if (IsRunning)
{
StartAnimation();
}
else
{
StopAnimation();
_rotationAngle = 0;
}
InvalidateVisual();
}
}
private void StartAnimation()
{
StopAnimation();
_timerSubscription = DispatcherTimer.Run(() =>
{
_rotationAngle += Frequency / 20.0;
if (_rotationAngle >= 360) _rotationAngle -= 360;
InvalidateVisual();
return true;
}, TimeSpan.FromMilliseconds(30));
}
private void StopAnimation()
{
_timerSubscription?.Dispose();
_timerSubscription = null;
}
public override void Render(DrawingContext context)
{
base.Render(context);
var bounds = new Rect(Bounds.Size);
var centerX = bounds.Width / 2;
var centerY = bounds.Height / 2 - 5;
var radius = Math.Min(bounds.Width, bounds.Height) / 2 - 15;
var typeface = new Typeface("Microsoft YaHei", FontStyle.Normal, FontWeight.Bold);
// 确定状态颜色
var statusColor = IsRunning ? RunningColor : StoppedColor;
var statusBrush = statusColor as SolidColorBrush ?? new SolidColorBrush(Colors.Gray);
// 绘制外圈发光效果(运行时)
if (IsRunning)
{
var glowBrush = new SolidColorBrush(statusBrush.Color, 0.2);
context.DrawEllipse(glowBrush, null, new Rect(
centerX - radius - 8,
centerY - radius - 8,
(radius + 8) * 2,
(radius + 8) * 2));
}
// 绘制外壳
var outerPen = new Pen(new SolidColorBrush(Color.Parse("#455A64")), 3);
context.DrawEllipse(null, outerPen, new Rect(
centerX - radius,
centerY - radius,
radius * 2,
radius * 2));
// 绘制内部背景
var innerBg = new SolidColorBrush(Color.Parse("#1E272E"));
context.DrawEllipse(innerBg, null, new Rect(
centerX - radius + 3,
centerY - radius + 3,
(radius - 3) * 2,
(radius - 3) * 2));
// 绘制泵叶片
var bladeCount = 6;
var bladeLength = radius * 0.65;
var bladeWidth = radius * 0.18;
for (int i = 0; i < bladeCount; i++)
{
var angle = _rotationAngle + (360.0 / bladeCount) * i;
var radians = angle * Math.PI / 180;
var bladeX = centerX + Math.Cos(radians) * bladeLength * 0.5;
var bladeY = centerY + Math.Sin(radians) * bladeLength * 0.5;
// 绘制叶片(带渐变效果)
var bladeBrush = new SolidColorBrush(IsRunning
? Color.FromArgb(200, statusBrush.Color.R, statusBrush.Color.G, statusBrush.Color.B)
: Color.Parse("#546E7A"));
var bladePath = new StreamGeometry();
using (var ctx = bladePath.Open())
{
ctx.BeginFigure(new Point(bladeX - bladeWidth / 2, bladeY - bladeLength / 2), true);
ctx.LineTo(new Point(bladeX + bladeWidth / 2, bladeY - bladeLength / 2));
ctx.LineTo(new Point(bladeX + bladeWidth / 2, bladeY + bladeLength / 2));
ctx.LineTo(new Point(bladeX - bladeWidth / 2, bladeY + bladeLength / 2));
ctx.EndFigure(true);
}
// 旋转叶片 - 使用矩阵变换
var rotationRadians = angle * Math.PI / 180;
var cos = Math.Cos(rotationRadians);
var sin = Math.Sin(rotationRadians);
var transform = new Matrix(cos, sin, -sin, cos, bladeX - bladeX * cos + bladeY * sin, bladeY - bladeX * sin - bladeY * cos);
using (context.PushTransform(transform))
{
context.DrawGeometry(bladeBrush, null, bladePath);
}
}
// 绘制中心圆(带渐变)
var centerRadius = radius * 0.25;
var centerBrush = new SolidColorBrush(IsRunning ? statusBrush.Color : Color.Parse("#455A64"));
context.DrawEllipse(centerBrush, null, new Rect(
centerX - centerRadius,
centerY - centerRadius,
centerRadius * 2,
centerRadius * 2));
// 中心高光
var highlightBrush = new SolidColorBrush(Colors.White, 0.3);
context.DrawEllipse(highlightBrush, null, new Rect(
centerX - centerRadius * 0.5,
centerY - centerRadius * 0.5,
centerRadius,
centerRadius));
// 绘制状态指示灯
var indicatorSize = 8;
var indicatorX = bounds.Width - 20;
var indicatorY = 10;
var indicatorBrush = IsRunning
? new SolidColorBrush(Color.Parse("#4CAF50"))
: new SolidColorBrush(Color.Parse("#78909C"));
// 指示灯发光
if (IsRunning)
{
context.DrawEllipse(new SolidColorBrush(indicatorBrush.Color, 0.3), null,
new Rect(indicatorX - 4, indicatorY - 4, 16, 16));
}
context.DrawEllipse(indicatorBrush, null,
new Rect(indicatorX, indicatorY, indicatorSize, indicatorSize));
// 绘制文字标签
if (!string.IsNullOrEmpty(Text))
{
var textBrush = new SolidColorBrush(Colors.White);
var text = new FormattedText(Text, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight, typeface, 11, textBrush);
var textPoint = new Point(
centerX - text.Width / 2,
bounds.Bottom - text.Height - 5);
context.DrawText(text, textPoint);
}
// 绘制频率显示
if (IsRunning)
{
var freqStr = $"{Frequency:F0}Hz";
var freqText = new FormattedText(freqStr, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 9,
new SolidColorBrush(statusBrush.Color));
context.DrawText(freqText, new Point(centerX - freqText.Width / 2, centerY + radius + 5));
}
}
protected override Size MeasureOverride(Size availableSize)
{
return new Size(70, 80);
}
}