You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带指定线性渐变画刷的WPF环形进度条

WPF固定色段环形进度条实现方案

核心思路

直接给进度圆弧绑定线性渐变会导致渐变随当前进度长度拉伸,低进度下就会提前出现后续色段,不符合需求。正确实现逻辑如下:

  • 将给定的线性渐变画刷的绘制范围固定为整个环形控件的外接矩形,不跟随进度圆弧的路径长度缩放
  • 使用Path搭配ArcSegment绘制环形,通过依赖属性绑定进度值,动态计算圆弧终点坐标
  • 仅渲染当前进度范围内的圆弧段,即可保证已绘制部分颜色固定,到达对应进度阈值才显示对应颜色

代码实现

1. 资源定义

先在窗口/控件资源中加入指定渐变和环形轨道底色:

<Window.Resources>
    <LinearGradientBrush x:Key="LinearGradientProgressBrush" 
                         StartPoint="0,0" EndPoint="1,1"
                         MappingMode="RelativeToBoundingBox">
        <GradientStop Color="Yellow" Offset="0"/>
        <GradientStop Color="Red" Offset="0.25"/>
        <GradientStop Color="Green" Offset="0.50"/>
        <GradientStop Color="Blue" Offset="0.75"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ProgressTrackBrush" Color="#E5E5E5" />
</Window.Resources>

2. 界面布局

用Grid叠加两层环形,底层为灰色轨道,上层为渐变进度条:

<Grid Width="200" Height="200" x:Name="ProgressContainer">
    <!-- 底部环形轨道 -->
    <Path Stroke="{StaticResource ProgressTrackBrush}"
          StrokeThickness="12"
          Data="M 100 10 A 90 90 0 1 1 99.9 10" />
    <!-- 渐变进度圆弧 -->
    <Path x:Name="ProgressArc"
          Stroke="{StaticResource LinearGradientProgressBrush}"
          StrokeThickness="12"
          StrokeStartLineCap="Round"
          StrokeEndLineCap="Round" />
</Grid>

3. 后台逻辑

添加进度依赖属性,进度变更时动态计算圆弧路径:

public partial class MainWindow : Window
{
    public double Progress
    {
        get => (double)GetValue(ProgressProperty);
        set => SetValue(ProgressProperty, value);
    }
    public static readonly DependencyProperty ProgressProperty =
        DependencyProperty.Register(nameof(Progress), typeof(double), typeof(MainWindow), 
            new PropertyMetadata(0.0, OnProgressChanged));

    // 环形参数,和界面尺寸对应
    private const double RingRadius = 90;
    private const double CenterX = 100;
    private const double CenterY = 100;

    private static void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var host = d as MainWindow;
        var progress = Math.Clamp((double)e.NewValue, 0, 1);
        host.UpdateArc(progress);
    }

    private void UpdateArc(double progress)
    {
        // 角度换算:WPF中0度对应3点钟方向,减去90度将起点移到12点钟方向
        double angle = progress * 360 - 90;
        double endX = CenterX + RingRadius * Math.Cos(angle * Math.PI / 180);
        double endY = CenterY + RingRadius * Math.Sin(angle * Math.PI / 180);
        bool isLargeArc = progress >= 0.5;

        // 构造当前进度对应的圆弧路径
        ProgressArc.Data = Geometry.Parse(
            $"M {CenterX} {CenterY - RingRadius} A {RingRadius} {RingRadius} 0 {Convert.ToInt32(isLargeArc)} 1 {endX} {endY}"
        );
    }

    public MainWindow()
    {
        InitializeComponent();
        // 测试动画:4秒跑完一圈循环播放
        var testAnim = new DoubleAnimation(0, 1, TimeSpan.FromSeconds(4))
        {
            RepeatBehavior = RepeatBehavior.Forever
        };
        BeginAnimation(ProgressProperty, testAnim);
    }
}

效果说明

  • 进度0~25%区间:圆弧从黄色平滑过渡到红色,已绘制段颜色固定
  • 进度25%~50%区间:圆弧终点从红色过渡到绿色,前25%段黄-红渐变保持不变
  • 进度50%~75%区间:圆弧终点从绿色过渡到蓝色,前50%段颜色完全固定
  • 进度达到75%后才会出现蓝色段,完全匹配需求

如果需要调整环形尺寸、粗细,同步修改界面中Grid的宽高、Path的StrokeThickness,以及后台代码中RingRadius、CenterX、CenterY参数即可。

内容的提问来源于stack exchange,提问作者chuckp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 10:45:38