WPF利用动画实现圆形进度条 原文:WPF利用动画实现圆形进度条
这是我的第一篇随笔,最近因为工作需要,开始学习WPF相关技术,自己想实现以下圆形进度条的效果,逛了园子发现基本都是很久以前的文章,实现方式一般都是GDI实现的,想到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="/winfx//xaml/presentation" 3 xmlns:x="/winfx//xaml" 4 xmlns:mc="/markup-compatibility/" 5 xmlns:d="/expression/blend/" 6 xmlns:ed="/expression//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> 21public partial class WaitingAndProgress : UserControl 22{ 23 #region 属性 24 25 private WaitAndProgressType showType = WaitAndProgressType.WaitingAndProgress; 26 /// <summary> 27 /// 当前样式类型 28 /// </summary> 29 [ponentModel.Browsable(true),ponentModel.Category("Appreance"),ponentModel.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位颜色值转为color101 /// </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 #endregion119 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 #endregion155 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>13public class ConverterCircleToPercent:IValueConverter14{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 }
转换类型 posted on -12-16 11:34 NET未来之路 阅读(...) 评论(...) 编辑 收藏