WPF 实现一个吃豆豆的Loading加载动画
运行的效果如下
先引入一下我们需要的库
在nuget上面搜一下"expression.Drawing",安装一下这个包
我们再创建一个Window,引入一下这个包的命名空间
我们设置一下这个加载动画呈现的窗体的样式
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" mc:Ignorable="d" WindowStyle="None" ResizeMode="NoResize" Background="#4C858585" WindowStartupLocation="CenterScreen" AllowsTransparency="True" Loaded="Window_Loaded" Title="Window1" Height="400" Width="400"
然后我们要用到我们添加的库里面的一个圆弧控件
<ed:Arc x:Name="arc" Height="100" Width="100" StrokeThickness="50" Panel.ZIndex="1" StartAngle="-240" EndAngle="-300" Stretch="None" ArcThicknessUnit="Pixel"> <ed:Arc.Stroke> <RadialGradientBrush GradientOrigin="0.3,0.3" RadiusX="0.7" RadiusY="0.7"> <GradientStop Color="#FFFFF00E" Offset="1"/> <GradientStop Color="White" Offset="0"/> </RadialGradientBrush> </ed:Arc.Stroke> </ed:Arc>
背景色设置成一个圆形渐变的原因是为了让这个控件看起来像一个球体,而不是一个圆,得到的效果如下:
再到下面放几个圆球
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" Margin="200,0,0,0"> <StackPanel x:Name="stackPanel" Orientation="Horizontal" RenderTransformOrigin="0.5,0.5">
<!--这里是为了后面的动画用,因为我是用blend添加的动画,所以生成的代码如下--> <StackPanel.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </StackPanel.RenderTransform> <Ellipse/> <Ellipse Margin="20,0"/> <Ellipse /> <Ellipse Margin="20,0"/> <Ellipse /> <Ellipse Margin="20,0"/> </StackPanel> </StackPanel>
资源里面添加一下这些球的大小和颜色
<Style TargetType="{x:Type Ellipse}"> <Setter Property="Height" Value="20"/> <Setter Property="Width" Value="20"/> <Setter Property="Fill" Value="#FFFF5800"/> </Style>
就会得到下面这个样子
我们再添加一下动画,让这两部分动起来
<Storyboard x:Key="Storyboard1" RepeatBehavior="Forever" AutoReverse="True"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="arc" Storyboard.TargetProperty="(ed:Arc.EndAngle)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="-300"/> <EasingDoubleKeyFrame KeyTime="00:00:0.25" Value="-271"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="arc" Storyboard.TargetProperty="(ed:Arc.StartAngle)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="-240"/> <EasingDoubleKeyFrame KeyTime="00:00:0.25" Value="-270"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Key="Storyboard2" RepeatBehavior="Forever"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="stackPanel" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <EasingDoubleKeyFrame KeyTime="00:00:01" Value="-78"/> </DoubleAnimationUsingKeyFrames> </Storyboard>
还需要把这个动画也动起来,在window的loaded事件里面添加下面的代码
private void Window_Loaded(object sender, RoutedEventArgs e) { var b = FindResource("Storyboard1") as Storyboard; b.Begin(); var c = FindResource("Storyboard2") as Storyboard; c.Begin(); }
这个时候运行这个窗体,就会发现已经实现了吃豆豆的效果,但是因为动画是一直在循环,小豆子一直往左边移动的时候,移动到一个位置就不会移动了,动画在重置的时候会让
动画看起来有一个延迟感,我们可以给这豆子的父级添加一个clip,让动画视觉上看起来是连续的(这里可以对比一下添加clip和不添加的效果的区别)
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" Margin="200,0,0,0"> <StackPanel.Clip> <RectangleGeometry> <RectangleGeometry.Rect> <Rect X="0" Y="0" Width="150" Height="40"/> </RectangleGeometry.Rect> </RectangleGeometry> </StackPanel.Clip> <StackPanel x:Name="stackPanel" Orientation="Horizontal" RenderTransformOrigin="0.5,0.5"> <!--这里是为了后面的动画用,因为我是用blend添加的动画,所以生成的代码如下--> <StackPanel.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </StackPanel.RenderTransform> <Ellipse/> <Ellipse Margin="20,0"/> <Ellipse /> <Ellipse Margin="20,0"/> <Ellipse /> <Ellipse Margin="20,0"/> </StackPanel> </StackPanel>
然后就是怎么把这个效果运用到我们的项目中
我们再添加一个window2,在里面添加一个button
button的click事件代码如下
我们运行window2,点击一下按钮,就会发现3秒钟以后,吃豆豆的动画就消失了,也就是数据加载完成,吃豆豆就不显示了
如果项目里面有很多的地方都要用到这个动画,我们可以添加一个类来专门做这个动画的事情
代码里面的Action就是我们需要耗时的一些操作
所以我们的button的click里面的代码就变成了下面这段代码
好了,到这里这个动画的实现就结束了
项目github地址:bearhanQ/WPFFramework: Share some experience (github.com)
QQ技术交流群:332035933;