【WPF】Blend制作WPF的动画
文章目录连续动画目标效果Blend实现动画的调用路径动画Blend实现效果演示启动动画(程序)关闭动画连续动画基础的Storyboard、时间线什么的概念就不在这里写了,因为这个博客也就是我自己记录自己学习的历程,我还没到可以教别人的程度用C#代码或者Xaml画一条线是很容易,但是要让线慢慢的一点点变长呢?用Timer计时器每隔一段时间修改line的宽度吗?不说Timer的时间精度问题,这样做出来
连续动画
基础的Storyboard、时间线什么的概念就不在这里写了,因为这个博客也就是我自己记录自己学习的历程,我还没到可以教别人的程度
用C#代码或者Xaml画一条线是很容易,但是要让线慢慢的一点点变长呢?用Timer计时器每隔一段时间修改line的宽度吗?不说Timer的时间精度问题,这样做出来想必也没有那么流畅的效果
目标效果
Blend实现
先创建一个Line的对象,放入Canvas容器内
<Line x:Name="line" X1="50" Y1="150" X2="500" Y2="150" Stroke="Green" StrokeThickness="1" Width="500"/>
然后在对象和时间线窗口中,点击图中的按钮,创建一个新的Stroyboard
在时间点0秒处,创建关键帧,最右侧的line对象属性窗口中设置width属性为0
同理,时间点5秒处,创建关键帧,width属性设置为line的最终宽度,点播放按钮预览效果
动画的调用
两种方法调用动画,一种在后台找到对应的storyboard资源使用start方法调用,另一种使用Blend直接在xaml中调用触发器
- 后台代码
var storyboard = (Storyboard)this.FindResources("Storyboard1");
storyboard.Start();
- xaml触发器
如下代码是Blend帮忙生成的
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource openStoryboard}"/>
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
<BeginStoryboard Storyboard="{StaticResource pathStoryboard}"/>
</EventTrigger>
</Window.Trigger>
等待效果
使用上次一模一样的操作,从阿里矢量图标库选取一个进度条的图片,然后时间点0设置角度为0,时间点3设置角度360,也可以设置相同的时间间隔转动不同的角度达到变速效果
<Storyboard x:Key="proStoryboard" RepeatBehavior="Forever" AutoReverse="False">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="proimage">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="60"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="180"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="240"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="300"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="360"/>
<!--<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="360"/>-->
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="proimage">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.0" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
路径动画
要想自己创建的对象按照某种路线移动,有两种方法,一种是上面提到的关键帧,某一时间点设置起始位置,然后设置不同的时间点拖动到不同的位置,造成可以移动的动画,但是这种方法弊端在于不能随心所欲的控制移动的位置,比如要想绕个圈那得设置多少个关键帧,而且弧度还不平滑,因为它只是针对TranslateTransform.X/Y属性,第二种方法就是使用路径动画,这种可以自己画好path,可以精确控制
Blend实现
<PathGeometry x:Key="PathGeometry1" Figures="M711.5,124 C711.5,124 628.5,257 766.5,221 904.5,185 1255.5025,96.499919 936.00088,146.00007 616.49922,195.50021 883.50077,102.49994 883.50077,102.49994 883.50077,102.49994 734.99988,-76.000585 771.00009,82.999882 807.00031,242.00035 942.00112,230.00031 942.00112,230.00031"/>
上面的代码是使用Blend的钢笔工具画出的一段路径,如下图
- DoubleAnimationUsingPath 路径动画的标签
- Duration 动画的时间间隔
- TargetName 动画操作的对象名
- TargetProperty 动画操作的属性,如放入Canvas容器内,可以为Canvs.Left/Top,不是的话属性设置为TranslateTransform.X/Y
- Source 绑定的Path的X或者Y
- PathGeometry 路径动画的路径
记不得标签的话,随便输入一个x或者y后Blend生成的代码中修改即可
<Storyboard x:Name="storyboard" x:Key="pathStoryboard" AutoReverse="True" RepeatBehavior="Forever">
<!--两种方法实现路径动画-->
<!--<DoubleAnimationUsingPath Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="X"/>-->
<!--<DoubleAnimationUsingPath Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="Y"/>-->
<DoubleAnimationUsingPath Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="X"/>
<DoubleAnimationUsingPath Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Duration="0:0:3" PathGeometry="{StaticResource PathGeometry1}" Storyboard.TargetName="movebtn" Source="Y"/>
</Storyboard>
效果演示
大方块使用第一种方法,小方块使用第二种方法
启动、关闭动画
Blend实现
也是使用连续动画的方式,操作的对象变成了window,操作的属性是width,控制窗体达到一个慢慢向右铺开的效果,但是如果设置窗体居中,铺开后窗体不会再正中,这个暂时没有解决
<!--控制window的旋转和缩放-->
<Window.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="scale" ScaleX="1" ScaleY="1"></ScaleTransform>
<RotateTransform x:Name="rotate" Angle="0"></RotateTransform>
</TransformGroup>
</Window.RenderTransform>
对于Window来说,右侧的属性窗口没有转换选项,但其实可以转换操作,不过要用代码实现,操作属性width可以实现铺开效果,而且右侧属性窗口是有width属性的,控制ScaleX和Scale Y属性从0-1控制缩放
<Storyboard x:Key="openStoryboard">
<DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)" From="0" To="1200" Duration="0:0:1" Storyboard.TargetName="window"/>
<!--<DoubleAnimation Storyboard.TargetProperty="ScaleX" From="0.1" To="1" Duration="0:0:1" Storyboard.TargetName="scale"/>-->
<!--<DoubleAnimation Storyboard.TargetProperty="ScaleY" From="0.1" To="1" Duration="0:0:1" Storyboard.TargetName="scale"/>-->
</Storyboard>
关闭也是操作width,不过是从展开后的宽度变为0,然后加上旋转,1秒转动720度(2圈),操作Opacity属性控制渐隐渐显效果,从1-0为渐隐
<Storyboard x:Key="closeStoryboard">
<DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)" From="1200" To="0" Duration="0:0:1" Storyboard.TargetName="window"/>
<DoubleAnimation Storyboard.TargetProperty="Angle" From="0" To="720" Duration="0:0:1" Storyboard.TargetName="rotate"/>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1" Storyboard.TargetName="grid"/>
</Storyboard>
启动动画Loaded事件加载,关闭动画需要在Closing事件中加载关闭动画然后阻止窗体关闭,在关闭动画执行结束后关闭窗体
public MainWindow()
{
InitializeComponent();
closeStoryboard = (Storyboard)this.FindResource("closeStoryboard");
closeStoryboard.Completed += (c, d) => Application.Current.Shutdown(); ;
}
private void window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
closeStoryboard.Begin();
e.Cancel = true;
}
如果启动动画、关闭动画出现黑色背景,多半是因为window的style没有设置为None,而且AllowsTransparency设置为true,标题栏需要自己画
效果演示
更多推荐
所有评论(0)