.Net-Avalonia学习笔记(十三)-创建半环形进度条控件

使用效果图:

1、前端代码:

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" d:DesignWidth="200" d:DesignHeight="100" Width="200" Height="100"
             x:Class="luoji_zebra_printer_BoardApp.CircularProgressBar" SizeChanged="UserControl_SizeChanged">
	<Grid Name="layout" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
		<Path Name="pathBack" Data="M8,99 A92,92 0 1 1 192,99" StrokeThickness="12" Stroke="#F0F0F0"/>
		<Path Name="path" Data="M8,99 A92,92 0 0 1 100,7" StrokeThickness="12" Stroke="#5064ff"/>
		<TextBlock Name="txtOEEValue" Text="50%" FontWeight="Bold" FontSize="30" Foreground="#5064ff" Margin="4,0,0,3" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
	</Grid>
</UserControl>

2、后端代码

using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using System.ComponentModel;
using System;

namespace luoji_zebra_printer_BoardApp;

public partial class CircularProgressBar : UserControl
{
    #region 属性
    // 值
    public static readonly StyledProperty<double> ValueProperty = AvaloniaProperty.Register<CircularProgressBar, double>(nameof(Value), 0);
    public double Value
    {
        get { return (double)GetValue(ValueProperty); }
        set
        {
            SetValue(ValueProperty, value);
            UpdateUI();
        }
    }
    // 背景色
    public static readonly StyledProperty<SolidColorBrush> BackColorProperty = AvaloniaProperty.Register<CircularProgressBar, SolidColorBrush>(nameof(BackColor));
    public SolidColorBrush BackColor
    {
        get { return (SolidColorBrush)GetValue(BackColorProperty); }
        set { SetValue(BackColorProperty, value); }
    }
    // 前景色
    public static readonly StyledProperty<SolidColorBrush> ForeColorProperty = AvaloniaProperty.Register<CircularProgressBar, SolidColorBrush>(nameof(ForeColor));
    public SolidColorBrush ForeColor
    {
        get { return (SolidColorBrush)GetValue(ForeColorProperty); }
        set { SetValue(ForeColorProperty, value); }
    }
    // 标题字体大小
    public static readonly StyledProperty<int> TitleSizeProperty = AvaloniaProperty.Register<CircularProgressBar, int>(nameof(TitleSize));
    public int TitleSize
    {
        get { return (int)GetValue(TitleSizeProperty); }
        set { SetValue(TitleSizeProperty, value); }
    }
    // 进度条宽度
    public static readonly StyledProperty<int> ProgressThicknessProperty = AvaloniaProperty.Register<CircularProgressBar, int>(nameof(ProgressThickness));
    public int ProgressThickness
    {
        get { return (int)GetValue(ProgressThicknessProperty); }
        set { SetValue(ProgressThicknessProperty, value); }
    }
    #endregion 属性

    #region 初始化
    public CircularProgressBar()
    {
        InitializeComponent();
        BackColor = SolidColorBrush.Parse("#F0F0F0");
        ForeColor = SolidColorBrush.Parse("#5064ff");
        TitleSize = 30;
        ProgressThickness = 12;
        Value = 50;
    }

    private void UserControl_SizeChanged(object? sender, Avalonia.Controls.SizeChangedEventArgs e)
    {
        UpdateUI();
    }
    #endregion 初始化

    /// <summary>
    /// 更新UI
    /// </summary>
    private void UpdateUI()
    {
        double width = Bounds.Width;
        double height = Bounds.Height;
        // 圆心坐标
        double middleX = Bounds.Width / 2, middleY = height - 1;
        // 半径
        double radius = (width - 16) / 2;

        if (radius <= 0) return;

        double xBC = 8;

        // pathBack
        double startX_Back = xBC;
        double endX_Back = width - xBC;
        string path_BackStr = $"M{startX_Back} {middleY}" +
            $" A{radius} {radius} 0 1 1" +
            $" {endX_Back} {middleY}";

        var conver_Back = TypeDescriptor.GetConverter(typeof(Geometry));
        pathBack.Data = (Geometry)conver_Back.ConvertFrom(path_BackStr);


        // path
        double value = Value < 0 ? 0 : Value;

        double startX = xBC;

        double angleInDegrees = value * 180 / 100;                    // 角度
        double angleInRadians = angleInDegrees * (Math.PI / 180.0);  // 转换为弧度
        // 计算终点的x,y
        double endX = radius * Math.Cos(angleInRadians);
        double endY = radius * Math.Sin(angleInRadians);
        endX = middleX - endX;
        endY = middleY - endY;

        string pathStr = $"M{startX_Back} {middleY}" +
            $" A{radius} {radius} 0 {(value < 100 ? 0 : 1)} 1" +
            $" {endX} {endY}";

        var converter = TypeDescriptor.GetConverter(typeof(Geometry));
        path.Data = (Geometry)converter.ConvertFrom(pathStr);


        // 其他
        pathBack.Stroke = BackColor;
        pathBack.StrokeThickness = ProgressThickness;
        path.Stroke = ForeColor;
        path.StrokeThickness = ProgressThickness;
        txtOEEValue.Text = Value + "%";
        txtOEEValue.FontSize = TitleSize;
    }
}
posted @ 2025-05-09 14:17  ꧁执笔小白꧂  阅读(146)  评论(0)    收藏  举报