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="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 }

转换类型

时间: 2024-10-03 18:42:00

WPF利用动画实现圆形进度条的相关文章

利用css3动画和border来实现圆形进度条

最近在学习前端的一些知识,发现border的功能十分强大啊! 首先来看看demo 就是这么一个圆形的进度条,在文本框中输入0-100的数值下面的进度条相应的转到多少 这个主要是利用border,旋转和css动画来实现的,主要思想是利用两个div来互相遮挡border形成的一个只有半圈有颜色的圆形,再利用旋转div的角度来调整显示 上代码: html+css+js(这里引入了jquery) <!DOCTYPE html> <html lang="en"> <

WPF 圆形进度条(一):整体框架

看了浸水的WPF 实现圆形进度条这篇文章,突发灵感,决定自己做一个圆形进度条(用户控件),名为LoadingRing. 首先,圆形进度条必定有一个Ellipse(这简直就是废话),所以需要一个Ellipse. 为了好看,我把它设为灰色并且半透明. 接着需要填充部分的控件,开始我想用Ellipse,并用StrokeDashArray来填充的,但是后来发现使用StrokeDashArray就难以使用动画.折腾半天,还是在Blend使用Arc形状好了.Arc中的StartAngle指定弧线的起始处,以

WPF 实现圆形进度条

项目中用到圆形进度条,首先就想到使用 ProgressBar 扩展一个,在园子里找到 迷途的小榔头 给出的思路和部分代码,自己加以实现.在此感谢 迷途的小榔头! 进度小于60显示红色,大于60则显示绿色.效果如下: 基本思路: 本质上是一个进度条,只是外观有别于矩形进度条,所以需要修改ProgressBar的ControlTemplate. 进度条部分实际是一个扇形,用WPF动态绘出(原理参考迷途的小榔头讲解). 要将进度条的值(Value依赖属性)转换为进度条,需要一个Converter. 根

HTML5动画(二):Canvas 实现圆形进度条并显示数字百分比

实现效果 1.首先创建html代码 <canvas id="canvas" width="500" height="500" style="background:#000;"></canvas> 2.创建canvas环境 var canvas = document.getElementById('canvas'), //获取canvas元素 context = canvas.getContext('2d

基于CAShapeLayer和贝塞尔曲线的圆形进度条动画【装载】

初次接触CAShapeLayer和贝塞尔曲线,看了下极客学院的视频.对初学者来说感觉还不错.今天来说一个通过CAShapeLayer和贝塞尔曲线搭配的方法,创建的简单的圆形进度条的教程先简单的介绍下CAShapeLayer1,CAShapeLayer继承自CALayer,可使用CALayer的所有属性2,CAShapeLayer需要和贝塞尔曲线配合使用才有意义.Shape:形状贝塞尔曲线可以为其提供形状,而单独使用CAShapeLayer是没有任何意义的.3,使用CAShapeLayer与贝塞尔

HTML5 canvas带渐变色的圆形进度条动画

query-circle-progress是一款带渐变色的圆形进度条动画特效jQuery插件.该圆形进度条使用的是HTML5 canvas来绘制圆形进度条及其动画效果,进度条使用渐变色来填充,效果非常的酷. 效果演示:http://www.htmleaf.com/Demo/201505271919.html 下载地址:http://www.htmleaf.com/html5/html5-canvas/201505271918.html

纯CSS3制作圆形进度条所遇到的问题

近日在开发的页面中,需要制作一个动态的圆形进度条,首先想到的是利用两个矩形,宽等于直径的一半,高等于直径,两个矩形利用浮动贴在一起,设置overflow:hidden属性,作为盒子,内部有一个与其宽高相等的子盒子,左侧的子盒子左上角和左下角以及右侧子盒子的右上角和右下角利用border-radius:半径,这样两个矩形便组成了一个完整的圆形. 我们让左侧的子盒子绕着右边的中点旋转180°,这样左侧的半圆就隐藏了,右侧半圆同理.这个地方设置旋转中心是用的transform-origin属性,第一个

Google Chrome 圆形进度条

Conmajia ? 2012 Updated on Feb. 21, 2018 Google Chrome 的圆形进度条. Demo 功能 显示百分比(0-100).如果进度值达到 100%,则将闪烁指定次数. 属性 BlinkCount,结束后闪烁几次.0 为不闪烁,默认 2. BlinkSpeed,闪烁速度,0-255,默认 10. Image,中央图标 SpokeColor,辐条颜色 SpokeCount,辐条数量 Value,进度百分比 事件 没有加入进度变化或完成事件. 原理和结构

自定义圆形进度条

关于控件呢,我想大家应该都很熟悉了吧,android应用开发MVC架构中,控件担任着至关重要的作用,感觉可以说是基于控件的事件模型人机交互的基础吧.这种特性感觉在wpf开发中体现得更为直接,感兴趣的同学可以去了解一下.而android框架自身就已经给我们提供了很多控件.那么问题来了?为什么有那么多控件可以用,你还要去屑自定义控件呢?是因为大家闲的蛋疼吗?显然不是.个人认为只要有两方面吧,要么是觉得有些原生控件是在是丑得难以忍受(即使是在你已经自定义了他的shape,圆角,selector等一系列