转载

WPF利用动画实现圆形进度条

这是我的第一篇随笔,最近因为工作需要,开始学习WPF相关技术,自己想实现以下圆形进度条的效果,逛了园子发现基本都是很久以前的文章,实现方式一般都是GDI实现的,想到WPF中动画效果不错,于是自己研究了一下,还真让我做出来了,废话不多说了,先上效果。

WPF利用动画实现圆形进度条

这个效果是不是还不错?这里面实现了数字实时显示以及根据进度进行自动渐变的效果。实现原理其实很简单,利用WPF动画,其中主要元素有border(实现里外层圆的效果),Arc扇面(就是用来实现外层填充效果的),Label(用来显示进度百分比)。

1.实现里外双层圆背景效果

这里我用了两个border实现,将两个border的CornerRadius设置为500,这样保证他们是两个圆(这里不用Ellipse是我觉得border可能更加省资源),然后将他们他们的宽度设置为100和80,让他们作为同心圆。其他设置主要为了美观此处不再多说,一会上代码即可。

2.利用Arc实现填充效果

说起这个Arc还真是个好东西,之前只是知道它是个扇面,但是没想到还可以实现弧度填充,这得益于它的ArcThickness可以设置为小数,这个具体数值可以在blend中自己调节一下,ArcThicknessUnit设置为Percent,意思是单位是百分比。然后利用Arc的StartAngle和EndAngle就可以轻松实现进度填充了。

3.利用Label实现进度显示

最后在中间放置一个Label,然后将它的Text属性绑定到Arc的EndAngle上,之后自己写个Convert将角度转化为百分比即可。

4.动画的实现

剩下的就可以利用blend做个动画,动画效果十分简单,开始时间,结束时间,开始角度,结束角度。这样简单的填充效果就实现了,最后还要实现渐变效果,好吧,其实也比较简单,同样的开始时间,结束时间,开始颜色,结束颜色,然后两个动画的时间间隔相同就好,这样效果比较同步。

注意:最后说一句,用ViewBox将整个效果框起来,这样以后无论你怎么拖拽这个空间,内部都不会出现变形的效果了。

代码如下:

   1 <UserControl x:Class="MyUserControlLibrary.WaitingAndProgress"  2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   6              xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"  7              xmlns:local ="clr-namespace:MyUserControlLibrary"  8              mc:Ignorable="d"   9              d:DesignHeight="100" d:DesignWidth="100" Loaded="UserControl_Loaded"> 10     <UserControl.Resources> 11         <local:ConverterCircleToPercent x:Key="converter"/> 12         <Storyboard x:Key="MainStoryboard" RepeatBehavior="Forever"> 13             <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="ShowArea"> 14                 <EasingDoubleKeyFrame KeyTime="0:0:1.6" Value="360"/> 15             </DoubleAnimationUsingKeyFrames> 16             <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="minCircle"> 17                 <EasingDoubleKeyFrame KeyTime="0:0:1.6" Value="360"/> 18             </DoubleAnimationUsingKeyFrames> 19         </Storyboard> 20         <Storyboard x:Key="FillStoryboard" Completed="Storyboard_Completed"> 21             <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(ed:Arc.EndAngle)" Storyboard.TargetName="FillArea"> 22                 <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 23                 <EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="0"/> 24             </DoubleAnimationUsingKeyFrames> 25             <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="FillArea"> 26                 <EasingColorKeyFrame KeyTime="0:0:0" Value="#FFFF0000"/> 27                 <EasingColorKeyFrame KeyTime="0:0:0.05" Value="#FF008000"/> 28             </ColorAnimationUsingKeyFrames> 29         </Storyboard> 30     </UserControl.Resources> 31     <Viewbox> 32     <Grid> 33             <Border Name="MaxCircle" CornerRadius="500" Width="100" Height="100" Background="White"  Opacity="0.2"/> 34             <Border Name="minCircle" CornerRadius="500" Width="80" Height="80" BorderBrush="black" BorderThickness="2" Opacity="0.4" RenderTransformOrigin="0.5,0.5"> 35                 <Border.RenderTransform> 36                     <TransformGroup> 37                         <ScaleTransform/> 38                         <SkewTransform/> 39                         <RotateTransform/> 40                         <TranslateTransform/> 41                     </TransformGroup> 42                 </Border.RenderTransform> 43                 <Border.Background> 44                     <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1"> 45                         <GradientStop Color="White" Offset="0"/> 46                         <GradientStop Color="Transparent" Offset="0.5"/> 47                         <GradientStop Color="White" Offset="1"/> 48                     </LinearGradientBrush> 49                 </Border.Background> 50             </Border> 51             <ed:Arc Name="FillArea" ArcThickness="0.18" ArcThicknessUnit="Percent" StartAngle="0" EndAngle="0" Width="95" Height="95" Stretch="None" Opacity="0.8" Fill="Red"/> 52             <Label Name="ShowLabel" Width="60" Height="60" FontFamily="宋体" FontWeight="Bold" Content="{Binding ElementName=FillArea,Path=EndAngle,Converter={StaticResource converter}}" FontSize="32" Foreground="White" Opacity="0.8" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" /> 53     </Grid> 54     </Viewbox> 55 </UserControl>  前端XMAL
    1 using System;   2 using System.Collections.Generic;   3 using System.Linq;   4 using System.Text;   5 using System.Windows;   6 using System.Windows.Controls;   7 using System.Windows.Data;   8 using System.Windows.Documents;   9 using System.Windows.Input;  10 using System.Windows.Media;  11 using System.Windows.Media.Animation;  12 using System.Windows.Media.Imaging;  13 using System.Windows.Navigation;  14 using System.Windows.Shapes;  15   16 namespace MyUserControlLibrary  17 {  18     /// <summary>  19     /// WaitingAndProgress.xaml 的交互逻辑  20     /// </summary>  21     public partial class WaitingAndProgress : UserControl  22     {  23         #region 属性  24   25         private WaitAndProgressType showType = WaitAndProgressType.WaitingAndProgress;  26         /// <summary>  27         /// 当前样式类型  28         /// </summary>  29         [System.ComponentModel.Browsable(true),System.ComponentModel.Category("Appreance"),System.ComponentModel.Description("设置或获取当前样式类型")]  30         public WaitAndProgressType ShowType {  31             get {  32                 return showType;  33             }  34             set {  35                 showType = value;  36             }  37         }  38   39         #endregion  40   41         public WaitingAndProgress()  42         {  43             InitializeComponent();  44         }  45   46         #region 方法  47   48         public void setPrecent(double d) {  49             if (showType == WaitAndProgressType.Waiting) {  50                 return;  51             }  52             Storyboard b = (Storyboard)this.Resources["FillStoryboard"];  53             DoubleAnimationUsingKeyFrames df = (DoubleAnimationUsingKeyFrames)b.Children[0];  54             ColorAnimationUsingKeyFrames cf = (ColorAnimationUsingKeyFrames)b.Children[1];  55             if (d >= 0 && d <= 10)  56             {  57                 cf.KeyFrames[1].Value = ToColor("#FFFF3300");  58             }  59             if (d > 10 && d <= 20)  60             {  61                 cf.KeyFrames[1].Value = ToColor("#FFFF6600");  62             }  63             if (d > 20 && d <= 30)  64             {  65                 cf.KeyFrames[1].Value = ToColor("#FFFF9900");  66             }  67             if (d > 30 && d <= 40)  68             {  69                 cf.KeyFrames[1].Value = ToColor("#FFFFCC00");  70             }  71             if (d > 40 && d <= 50)  72             {  73                 cf.KeyFrames[1].Value = ToColor("#FFFFFF00");  74             }  75             if (d > 50 && d <= 60)  76             {  77                 cf.KeyFrames[1].Value = ToColor("#FFCCFF00");  78             }  79             if (d > 60 && d <= 70)  80             {  81                 cf.KeyFrames[1].Value = ToColor("#FF99FF00");  82             }  83             if (d > 70 && d <= 80)  84             {  85                 cf.KeyFrames[1].Value = ToColor("#FF66FF00");  86             }  87             if (d > 80 && d <= 90)  88             {  89                 cf.KeyFrames[1].Value = ToColor("#FF33FF00");  90             }  91             if (d > 90 && d <= 100)  92             {  93                 cf.KeyFrames[1].Value = ToColor("#FF00FF00");  94             }  95             df.KeyFrames[1].Value = d*3.6;  96             b.Begin();  97         }  98   99         /// <summary> 100         /// 将blend的8位颜色值转为color 101         /// </summary> 102         /// <param name="colorName"></param> 103         /// <returns></returns> 104         public Color ToColor(string colorName) 105         { 106             if (colorName.StartsWith("#")) 107                 colorName = colorName.Replace("#", string.Empty); 108             int v = int.Parse(colorName, System.Globalization.NumberStyles.HexNumber); 109             return new Color() 110             { 111                 A = Convert.ToByte((v >> 24) & 255), 112                 R = Convert.ToByte((v >> 16) & 255), 113                 G = Convert.ToByte((v >> 8) & 255), 114                 B = Convert.ToByte((v >> 0) & 255) 115             }; 116         } 117  118         #endregion 119  120         #region 事件 121  122         //载入时事件处理 123         private void UserControl_Loaded(object sender, RoutedEventArgs e) 124         { 125             if (showType != WaitAndProgressType.Progress) 126             { 127                 Storyboard b1 = (Storyboard)this.Resources["MainStoryboard"]; 128                 b1.Begin(); 129                 if (showType == WaitAndProgressType.Waiting) 130                 { 131                     ShowLabel.Visibility = System.Windows.Visibility.Hidden; 132                 } 133                 else { 134                     ShowLabel.Visibility = System.Windows.Visibility.Visible; 135                 } 136             } 137             else { 138                 Storyboard b1 = (Storyboard)this.Resources["MainStoryboard"]; 139                 b1.Stop(); 140                 ShowLabel.Visibility = System.Windows.Visibility.Visible; 141             } 142         } 143  144         //渐变动画完成时 145         private void Storyboard_Completed(object sender, EventArgs e) 146         { 147             Storyboard b = (Storyboard)this.Resources["FillStoryboard"]; 148             ColorAnimationUsingKeyFrames cf = (ColorAnimationUsingKeyFrames)b.Children[1]; 149             DoubleAnimationUsingKeyFrames df = (DoubleAnimationUsingKeyFrames)b.Children[0]; 150             df.KeyFrames[0].Value = df.KeyFrames[1].Value; 151             cf.KeyFrames[0].Value = cf.KeyFrames[1].Value; 152         } 153  154         #endregion 155  156          157     } 158 }  后台代码
   1 using System;  2 using System.Collections.Generic;  3 using System.Globalization;  4 using System.Linq;  5 using System.Text;  6 using System.Windows.Data;  7   8 namespace MyUserControlLibrary  9 { 10     /// <summary> 11     /// 将角度转化成百分比 12     /// </summary> 13     public class ConverterCircleToPercent:IValueConverter 14     { 15         public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16         { 17             return (int)(double.Parse(value.ToString()) * 10 / 36); 18         } 19         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20         { 21             throw new NullReferenceException(); 22         } 23     } 24 }  转换类型
正文到此结束
Loading...