WPF动画 - Loading加载动画
存在问题:
最近接手公司一个比较成熟的产品项目开发(WPF桌面端),其中,在登陆系统加载时,60张图片切换,实现loading闪烁加载,快有密集恐惧症了!!!
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private void LoadPics() { try { _storyboard = new Storyboard(); for (int i = 0; i < 60; i++) { ObjectAnimationUsingKeyFrames oauf = new ObjectAnimationUsingKeyFrames(); //ObjectAnimationUsingKeyFrames 可以对指定 Duration 内的一组 KeyFrames 中的 Object 属性值进行动画处理 BitmapImage bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.UriSource = new Uri("pack://application:,,,/jg.CloudCube.WPF;component/Resources/LoadingAnimation/loading" + (i + 1) + ".png"); bitmap.CacheOption = BitmapCacheOption.Default; bitmap.EndInit(); ImageBrush imgBrush = new ImageBrush(bitmap); //读取图片文件 DiscreteObjectKeyFrame dokf = new DiscreteObjectKeyFrame(); //DiscreteObjectKeyFrame 通过使用离散内插,可以在前一个关键帧的 Object 值及其自己的 Value 之间进行动画处理。 dokf.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(i * 30)); //KeyTime 获取或设置应到达关键帧的目标 Value 的时间 //这里每隔40毫秒设置一张图片,也就是每秒1000/40=25帧 dokf.Value = imgBrush; oauf.KeyFrames.Add(dokf); Storyboard.SetTargetProperty(oauf, new PropertyPath("(Rectangle.Fill)")); //把动画应用到窗体的Rectangle中 Storyboard.SetTarget(oauf, RectDis); //RectDis是Rectangle的名称 _storyboard.Children.Add(oauf); //把ObjectAnimationUsingKeyFrames动画添加到Storyboard中 } _storyboard.RepeatBehavior = RepeatBehavior.Forever; } catch (Exception ex) { var log = log4net.LogManager.GetLogger("Error"); log.Error(ex.Message, ex); } }
60张图:
这样的实现效果,实在对不住 WPF对动画那么好的支持。
解决方式:
下面使用WPF(Storyboard)只在xaml中,实现Loading加载闪烁动画。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<Window x:Class="TestWpf.Window4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="Window4" Height="300" Width="300"> <Window.Resources> <Style x:Key="FlashStyle" TargetType="{x:Type FrameworkElement}"> <Style.Triggers> <EventTrigger RoutedEvent="Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Opacity)" BeginTime="00:00:00" From="1" To="0" Duration="00:00:01.5" AutoReverse="True" RepeatBehavior="Forever"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Style.Triggers> </Style> <Storyboard x:Key="StoryLeftToRight" RepeatBehavior="Forever" Duration="00:00:01.5"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="e1" Storyboard.TargetProperty="(FrameworkElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.0" Value="1" /> <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:01.0" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:01.5" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="e2" Storyboard.TargetProperty="(FrameworkElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.0" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="1" /> <SplineDoubleKeyFrame KeyTime="00:00:01.0" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:01.5" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="e3" Storyboard.TargetProperty="(FrameworkElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.0" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:01.0" Value="1" /> <SplineDoubleKeyFrame KeyTime="00:00:01.5" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="e4" Storyboard.TargetProperty="(FrameworkElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.0" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:01.0" Value="0" /> <SplineDoubleKeyFrame KeyTime="00:00:01.5" Value="1" /> </DoubleAnimationUsingKeyFrames> </Storyboard> </Window.Resources> <Grid Background="DeepSkyBlue"> <StackPanel Orientation="Horizontal" Margin="20" VerticalAlignment="Bottom" HorizontalAlignment="Right"> <TextBlock Text="Loading " Style="{StaticResource FlashStyle}" Foreground="White" FontSize="20"/> <StackPanel Orientation="Horizontal"> <StackPanel.Triggers> <EventTrigger RoutedEvent="FrameworkElement.Loaded"> <BeginStoryboard Storyboard="{StaticResource StoryLeftToRight}" /> </EventTrigger> </StackPanel.Triggers> <Ellipse Name="e1" Width="5" Height="5" Margin="5,0,0,0" HorizontalAlignment="Left" Fill="White" /> <Ellipse Name="e2" Width="5" Height="5" Margin="5,0,0,0" HorizontalAlignment="Left" Fill="White" /> <Ellipse Name="e3" Width="5" Height="5" Margin="5,0,0,0" HorizontalAlignment="Left" Fill="White" /> <Ellipse Name="e4" Width="5" Height="5" Margin="5,0,0,0" HorizontalAlignment="Left" Fill="White" /> </StackPanel> </StackPanel> </Grid> </Window>
实现效果:
技术要点:
DoubleAnimation属性介绍:
Storyboard.TargetName:附加属性操作到指定的对象上;
Storyboard.TargetProperty:要操作指定对象的属性;
From..To :上述属性值的起始范围;
Duration: 在多少时间内完成上述属性值的变化;
RepeatBehavior:反复次数;
AutoReverse:完成向迭代后是否按相反的顺序播放
System.Windows.Media.Animation提供三种动画类线性插值动画类(17个)、关键帧动画(22个)、路径动画(3个).
参考: http://www.cnblogs.com/libaoheng/archive/2012/04/23/2466242.html