• wpf 水波进度条 用户控件


    之前看公司web前端做了个 圆形的水波纹 进度条,就想用wpf 做一个,奈何自己太菜 一直做不出来,在看过 “普通的地球人” 的 “

    WPF实现三星手机充电界面 博客之后 我也来照葫芦画个瓢。

    废话不多说 先贴一下效果图

    虽然样子 low 了些 但是基本满足我的需求了,下面是代码

    前端

    <UserControl x:Class="WaveProgress.UserControl.WaveProgressControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WaveProgress.UserControl"
                 mc:Ignorable="d" 
                 Height="150" Width="150" x:Name="wave_control">
        <UserControl.Resources>
            <Storyboard x:Key="WaterStoryboard">
                <PointAnimation Storyboard.TargetName="bs_Water" DesiredFrameRate="20" Storyboard.TargetProperty="Point1" From="90,60" To="90,90" Duration="00:00:2" AutoReverse="True" RepeatBehavior="Forever"></PointAnimation>
                <PointAnimation Storyboard.TargetName="bs_Water" DesiredFrameRate="20" Storyboard.TargetProperty="Point2" From="100,110" To="100,95" Duration="00:00:1.8" AutoReverse="True" RepeatBehavior="Forever"></PointAnimation>
            </Storyboard>
        </UserControl.Resources>
        <Grid Width="{Binding ElementName=wave_control,Path=Width}" Height="{Binding ElementName=wave_control,Path=Height}" 
              Background="{Binding WaveProgressBackground,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
            <Grid.Clip>
                <EllipseGeometry Center="75,75" RadiusX="75" RadiusY="75" ></EllipseGeometry>
            </Grid.Clip>
            <StackPanel Width="150" VerticalAlignment="Bottom">
                <Path Fill="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
                    <Path.Data>
                        <PathGeometry FillRule="EvenOdd" >
                            <PathFigure StartPoint="0,90" >
                                <BezierSegment x:Name="bs_Water" Point1="90,60" Point2="100,110" Point3="150,90"></BezierSegment>
                                <PolyLineSegment Points="150,100 0,100"></PolyLineSegment>
                            </PathFigure>
                        </PathGeometry>
                    </Path.Data>
                    <Path.Triggers>
                        <EventTrigger RoutedEvent="Path.Loaded">
                            <BeginStoryboard Storyboard="{StaticResource WaterStoryboard}"></BeginStoryboard>
                        </EventTrigger>
                    </Path.Triggers>
                </Path>
                <Rectangle Height="{Binding WaveProgressHeight,UpdateSourceTrigger=PropertyChanged}" Fill="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            </StackPanel>
            <Ellipse VerticalAlignment="Bottom" Width="150" Height="150" Stroke="{Binding WaveBorderBrush,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Fill="Transparent" 
                     StrokeThickness="{Binding WaveBorderThickness,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="22" Foreground="{Binding TextColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
                <Run Text="{Binding DisPlayValue,UpdateSourceTrigger=PropertyChanged}"></Run>
                <Run Text="%"></Run>
            </TextBlock>
        </Grid>
    </UserControl>

    后台

    using System.Globalization;
    using System.Windows;
    using System.Windows.Media;
    
    namespace WaveProgress.UserControl
    {
        /// <summary>
        /// WaveProgressControl.xaml 的交互逻辑
        /// </summary>
        public partial class WaveProgressControl : System.Windows.Controls.UserControl
        {
            public WaveProgressControl()
            {
                InitializeComponent();
                this.DataContext = this;
            }
    
            public static readonly DependencyProperty WaveProgressBackgroundProperty = DependencyProperty.Register(
                "WaveProgressBackground", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.White));
    
            /// <summary>
            /// 进度条背景色
            /// </summary>
            public SolidColorBrush WaveProgressBackground
            {
                get { return (SolidColorBrush) GetValue(WaveProgressBackgroundProperty); }
                set { SetValue(WaveProgressBackgroundProperty, value); }
            }
    
            public static readonly DependencyProperty WaveBorderBrushProperty = DependencyProperty.Register(
                "WaveBorderBrush", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.Blue));
            /// <summary>
            /// 边框颜色
            /// </summary>
            public SolidColorBrush WaveBorderBrush
            {
                get { return (SolidColorBrush) GetValue(WaveBorderBrushProperty); }
                set { SetValue(WaveBorderBrushProperty, value); }
            }
    
            public static readonly DependencyProperty WaveBorderThicknessProperty = DependencyProperty.Register(
                "WaveBorderThickness", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(2.0));
    
            /// <summary>
            /// 边框粗细
            /// </summary>
            public double WaveBorderThickness
            {
                get { return (double) GetValue(WaveBorderThicknessProperty); }
                set { SetValue(WaveBorderThicknessProperty, value); }
            }
    
         
            public static readonly DependencyProperty WavePorgressBarColorProperty = DependencyProperty.Register(
                "WavePorgressBarColor", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.Red));
            /// <summary>
            /// 进度条颜色
            /// </summary>
            public SolidColorBrush WavePorgressBarColor
            {
                get { return (SolidColorBrush) GetValue(WavePorgressBarColorProperty); }
                set { SetValue(WavePorgressBarColorProperty, value); }
            }
    
            public static readonly DependencyProperty TextColorProperty = DependencyProperty.Register(
                "TextColor", typeof(SolidColorBrush), typeof(WaveProgressControl), new PropertyMetadata(Brushes.Black));
            /// <summary>
            /// 文字颜色
            /// </summary>
            public SolidColorBrush TextColor
            {
                get { return (SolidColorBrush) GetValue(TextColorProperty); }
                set { SetValue(TextColorProperty, value); }
            }
    
            public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
                "Value", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(default(double)));
    
            /// <summary>
            /// 当前进度
            /// </summary>
            public double Value
            {
                get { return (double) GetValue(ValueProperty); }
                set { SetValue(ValueProperty, value); }
            }
    
            public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register(
                "MaxValue", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(default(double)));
    
            public double MaxValue
            {
                get { return (double) GetValue(MaxValueProperty); }
                set { SetValue(MaxValueProperty, value); }
            }
    
            public static readonly DependencyProperty DisPlayValueProperty = DependencyProperty.Register(
                "DisPlayValue", typeof(string), typeof(WaveProgressControl), new PropertyMetadata("0"));
    
            public string DisPlayValue
            {
                get { return (string) GetValue(DisPlayValueProperty); }
                set { SetValue(DisPlayValueProperty, value); }
            }
    
            public static readonly DependencyProperty WaveProgressHeightProperty = DependencyProperty.Register(
                "WaveProgressHeight", typeof(double), typeof(WaveProgressControl), new PropertyMetadata(default(double)));
    
            /// <summary>
            /// 次属性不要手动设置
            /// </summary>
            public double WaveProgressHeight
            {
                get { return (double) GetValue(WaveProgressHeightProperty); }
                set { SetValue(WaveProgressHeightProperty, value); }
            }
    
            protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
            {
                base.OnPropertyChanged(e);
                if (e.Property == ValueProperty)
                {
                    double bl = Value / MaxValue;
                    WaveProgressHeight = 140 * bl;
                    DisPlayValue = (bl * 100).ToString(CultureInfo.InvariantCulture);
                }
            }
        }
    
    }

    美中不足的是:

    1、大小是我写死了的,因为里面那个水波是用path 写的 是个固定的

    2、仔细看 中间有条白色的线(等有时间在解决吧)

     

    学习到的知识:

    1、学会用贝塞尔曲线,和它的动画

    2、学会了Clip剪裁

    3、看大佬的文章果然受益匪浅

     

    附:解决有一条白线的问题

    将水波纹进度条的 边线设置为0,代码为:

    <Path SnapsToDevicePixels="True" 
                      Fill="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
                      Stroke="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
                      StrokeThickness="0">
                    <Path.Data>
                        <PathGeometry FillRule="EvenOdd" >
                            <PathFigure StartPoint="0,90" >
                                <BezierSegment x:Name="bs_Water" Point1="90,60" Point2="100,110" Point3="150,90"></BezierSegment>
                                <PolyLineSegment Points="150,100 0,100"></PolyLineSegment>
                            </PathFigure>
                        </PathGeometry>
                    </Path.Data>
                    <Path.Triggers>
                        <EventTrigger RoutedEvent="Path.Loaded">
                            <BeginStoryboard Storyboard="{StaticResource WaterStoryboard}"></BeginStoryboard>
                        </EventTrigger>
                    </Path.Triggers>
                </Path>
                <Rectangle SnapsToDevicePixels="True" Height="{Binding WaveProgressHeight,UpdateSourceTrigger=PropertyChanged}" Fill="{Binding WavePorgressBarColor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>

    将此代码直接覆盖 原有代码即可(StackPanel 中的那两个控件)

    附源码:https://github.com/t115liyanpeng/WaveProgress

    不想平凡,奈何太懒 T_T
  • 相关阅读:
    spring boot 打包 jar 实现第三方零配置引用
    spring boot 整合log4j2
    linux cat 模糊查询日志命令
    docker深入浅出
    docker容器为啥一定要前台运行
    李诚云原生技术分享
    k8s中对应的stateful有状态服务的讲解
    k8s networkpolicy网络策略详解
    k8s中IngressIp和egressIp的区别
    技术丨小团队微服务落地实践
  • 原文地址:https://www.cnblogs.com/wuyaxiansheng/p/10478574.html
Copyright © 2020-2023  润新知